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