0

I have an exercise for which I have to implement a function that takes as parameters a one-parameter function pointer fun, a parameter to the function pointed at by said pointer parameter and an integer period. This function will return either 1 in case the execution of the function fun points to with parameter as parameter terminates before period seconds, or 0 if not.

Are these two solutions equivalent?

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;
}

And:

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;
}

I'd say yes, but I'd like to clear up any doubt I might have.

WIlopu
  • 47
  • 7

1 Answers1

1

These are not the same.

In the first example, if the alarm is triggered, fun does not exit normally due to the call to siglongjmp. In the second example, the alarm will set the flag for the return value, but fun will continue to run to completion.

Also, you have a bug here:

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

You're missing braces around the if and else blocks, and missing the ; after the first return. Also I believe you have the return values mixed up based on your description of what the function should do.

The fixed code:

  if(sigsetjmp(env,1) == 0) {
    fun(parameter);
    sigaction(SIGALRM, &old, NULL);
  } else {
    return 1;
  }
  return 0;
dbush
  • 205,898
  • 23
  • 218
  • 273
  • You are right, I got the return values mixed up (fixed that). And yes it is obvious that `fun` will run to completion with the second code, unlike with the first. But the end result is the same, isn't it? – WIlopu Dec 10 '15 at 19:00
  • @WIlopu If by "end result is the same" you mean "does `execution_time_limit` return the value you expect in both cases" then yes. However, in the second case, if you set `period` to 5 but `fun` takes 60 seconds to run, then `execution_time_limit` won't return until the 60 seconds is done. If you want `execution_time_limit` to run no longer than `period`, use the second method. – dbush Dec 10 '15 at 19:03
  • That what I figured, it is nice to have confirmation. Thank you. – WIlopu Dec 10 '15 at 19:05
  • Further bugs. The first example will leave SIGALRM set to `myalarm` if we long jump. ([SA_RESETHAND](http://pubs.opengroup.org/onlinepubs/007908775/xsh/sigaction.html) would avoid this.) Neither example turns off the alarm if `fun` completes in time — I hope the rest of the code is ready for a long jump or EINTR! Finally, `alarm` is inherently race-prone in uses like this, even if we attempt to disable before the timeout. For the OP's purposes, it'd be easier just to time `fun`'s execution and avoid signals completely. – pilcrow Dec 10 '15 at 21:52