longjmp() from nested signal handlers
Tom Stockfisch
ix426 at sdcc6.ucsd.EDU
Wed Apr 6 14:32:54 AEST 1988
In article <26739 at amdahl.uts.amdahl.com> nw at amdahl.uts.amdahl.com (Neal Weidenhofer) writes:
>... Using longjump from a signal handler ALWAYS results in
>undefined behavior.
This *greatly* reduces the value of signals.
I like to longjmp() back to a main processing loop on SIGINT. If
all I do is set a flag and return,
then I have to check that flag in a million other places to see if a user
is trying to get my attention.
The situation is even worse if the behavior is undefined for longjmp()ing
out of a signal handler for SIGFPE. If you RETURN from a SIGFPE handler
the behavior is *badly* undefined -- you could be in an infinite loop.
>My favorite example is to consider the case of the signal being
>raised while the program is in the middle of malloc(3) (for UN*X
>types--something equivalent if you're using VMS or some other
>OS). There is NO WAY that your program is going to continue to
>run correctly after control has been forcibly removed from some
>routine while its internal tables are in an inconsistent state.
You can avoid this by protecting all sections of code that shouldn't
be abandoned half-way thru:
signal( SIGINT, on_sigint );
...
protect();
...
p = malloc(SIZE);
update_linked_list();
...
unprotect();
...
-----------
on_sigint.c
-----------
static bool interrupt_ok = TRUE;
static bool interrupt_pending = FALSE;
void
protect()
{
interrupt_ok = FALSE;
}
void
unprotect()
{
interrupt_ok = TRUE;
if ( interrupt_pending )
{
interrupt_pending = FALSE;
on_sigint();
}
}
void
on_sigint()
{
if ( !interrupt_ok )
{
interrupt_pending = TRUE;
return;
}
fprintf( stderr, "\n<interrupt>\n" );
longjmp( main_loop );
}
>This is why dpANS limits signal handlers to setting a flag and
>returning. Most compilers and/or OS's are going to have to do
>some work even to get this right.
>...
> Neal Weidenhofer
I thought unix implementers these days use a similar scheme to
protect sensitive portions of kernel and library function code.
I suppose it would be asking to much to require all C implementations
to do this. I don't mind enclosing malloc() calls with protect()/unprotect(),
and I usually have some uninterruptable code of my own next to
these calls, but I wouldn't want to have to surround every getc(), printf(),
etc.
Anyway, if anyone is still listening, what versions of unix *do not*
sensitive system code from interrupts?
--
|| Tom Stockfisch, UCSD Chemistry tps at chem.ucsd.edu
More information about the Comp.lang.c
mailing list