【问题标题】:Using sigaction with or without sigsetjmp在有或没有 sigsetjmp 的情况下使用 sigaction
【发布时间】:2015-12-10 18:15:54
【问题描述】:

我有一个练习,我必须实现一个函数,该函数将一个参数函数指针fun、一个指向由所述指针parameter 指向的函数的参数和一个整数period 作为参数。如果函数funparameter 作为参数在period 秒之前终止,则此函数将返回1,否则返回0。

这两种解决方案是否等效?

static struct sigaction sa, old;
static jmp_buf env;

static void myalarm(int sig)
{
  printf("alarm!\n");
  siglongjmp(env,1);
}

int execution_time_limit( void (*fun)(void *), void *parameter, int period)
{
  sa.sa_handler = myalarm;
  sa.sa_flags = 0; 
  sigemptyset(&sa.sa_mask);
  sigaction(SIGALRM, &sa, &old);

  alarm(period);
  if(sigsetjmp(env,1) == 0) {
    fun(parameter);
    sigaction(SIGALRM, &old, NULL);
  }
  else
    return 0;
 return 1;
}

还有:

static struct sigaction sa, old;
static jmp_buf env;
int ret = 0;

static void myalarm(int sig)
{
  printf("alarm!\n");
  ret = 1;
}

int execution_time_limit( void (*fun)(void *), void *parameter, int period)
{
  sa.sa_handler = myalarm;
  sa.sa_flags = 0; 
  sigemptyset(&sa.sa_mask);
  sigaction(SIGALRM, &sa, &old);

  alarm(period);
  fun(parameter);
  sigaction(SIGALRM, &old, NULL);
  return ret;
}

我会说是的,但我想澄清我可能有的任何疑问。

【问题讨论】:

    标签: c signals sigaction


    【解决方案1】:

    这些不一样。

    在第一个例子中,如果触发了警报,由于调用了siglongjmpfun 不会正常退出。在第二个示例中,警报将为返回值设置标志,但fun 将继续运行直至完成。

    另外,这里有一个错误:

      if(sigsetjmp(env,1) == 0) 
        fun(parameter);
        sigaction(SIGALRM, &old, NULL);
      else
        return 0
      return 1;
    

    您在ifelse 块周围缺少大括号,并且在第一个return 之后缺少;。此外,我相信您根据您对函数应该做什么的描述混淆了返回值。

    固定代码:

      if(sigsetjmp(env,1) == 0) {
        fun(parameter);
        sigaction(SIGALRM, &old, NULL);
      } else {
        return 1;
      }
      return 0;
    

    【讨论】:

    • 你是对的,我把返回值弄混了(修复了)。是的,很明显fun 将与第二个代码一起运行完成,这与第一个不同。但最终的结果是一样的,不是吗?
    • @WIlopu 如果“最终结果相同”是指“execution_time_limit 在两种情况下都返回您期望的值”,那么是的。但是,在第二种情况下,如果您将 period 设置为 5 但 fun 需要 60 秒才能运行,那么 execution_time_limit 将在 60 秒完成之前返回。如果您希望execution_time_limit 运行时间不超过period,请使用第二种方法。
    • 这就是我的想法,很高兴得到确认。谢谢。
    • 更多错误。如果我们跳远,第一个示例将使 SIGALRM 设置为myalarm。 (SA_RESETHAND 会避免这种情况。)如果fun 及时完成,这两个示例都不会关闭警报 - 我希望其余代码已准备好进行跳远或 EINTR!最后,alarm 在这样的使用中本质上是容易竞争的,即使我们尝试在超时之前禁用。出于 OP 的目的,只为 fun 的执行计时并完全避免信号会更容易。
    猜你喜欢
    • 2020-08-18
    • 2017-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-13
    • 2013-04-03
    • 1970-01-01
    • 2014-12-28
    相关资源
    最近更新 更多