views:

115

answers:

3

Similar to this question, I'd like to limit the execution time of a function--preferably with microsecond accuracy--in C. I imagine that C++ exceptions could be used to achieve a result similar to this Python solution. Though it's not ideal, such an approach is wholly unavailable in plain C.

I wonder, then, how might I interrupt the execution of a function after a certain time interval in C on a Posix system? For relatively simple situations a bit of silly business works just fine, but that adds a fair amount of code orthogonal to the problem solution. Let's say I have a function like so:

void boil(egg *e) {
    while (true)
    do_boil(e);
}

I want to run run boil on an egg*, interrupting it every 50μs to check do something like so:

egg *e = init_egg();
while (true) {
    preempt_in(50, (void) (*boil), 1, e);
    /* Now boil(e) is executed for 50μs, 
       then control flow is returned to the
       statement prior to the call to preempt_in.
     */
    if (e->cooked_val > 100)
        break;
}

I realize that pthreads could be used to do this, but I'm rather more interested in avoiding their use. I could switch between ucontext_t's in a SIGALRM handler, but the POSIX standard notes that the use of setcontext/swapcontext is not to be used in a signal handler and, indeed, I note differing behaviors between Linux and Solaris systems when doing so.

Is this effect possible to achieve? If so, in a portable manner?

+1  A: 

You can either use threads, or have the function poll a timer (or a global variable set by SIGALRM handler), then save its state and exit when the allotted time has expired. Use of ucontext_t is deprecated and should never be used in new code, at all, much less from signal handlers.

R..
Citation on `ucontext_t` deprecation? I thought the associated functions just weren't widely implemented.
llasram
A quick google for `ucontext deprecated` finds things about particular vendors, especially Apple, marking them as deprecated. As for official deprecation, I don't have the citation right off, but I seem to remember SUSv3 deprecating some or all of the functionality due to the fact that C99 made some of the pointer cast constructs it requires undefined behavior. I'd have to look again to be sure though...
R..
I'm supposing, then, that your answer is no. I will either have to poll, or introduce threads, in your estimation.
troutwine
A: 

The solution I desire suddenly occurs to me: goto! I'll setup a jump point just after the function I wish to limit, set a timer and in the signal handler which deals with the SIG*ALRM simply jump to the instruction after the function.

troutwine
If that's the effect you want, then why can't you just use `sigsetjmp()`/`siglongjmp()`? Noting that `goto` does not in fact work across function boundaries.
llasram
Quite right, goto does have only function scope. While the use of \*jmp has a few deficiencies, it _mostly_ gets me where I want to go. I simply didn't think of it because "Goto is Harmful" had been for so long pounded into my head.
troutwine
A: 
andersoj
Excellent; thank you.
troutwine