longjmp out of signal handler (was Re: alloca() portability)

Richard Harter rh at smds.UUCP
Tue Nov 20 17:55:34 AEST 1990


In article <1990Nov16.181436.21736 at zoo.toronto.edu>, henry at zoo.toronto.edu (Henry Spencer) writes:

> In case Chris doesn't have paragraphs to spare right now, here's a few
> sentences. :-)  It is extremely difficult to guarantee that anything
> will work portably in signal handlers, because the stranger C environments
> put bizarre restrictions on them due to difficulties with calling conventions
> and the like.  ANSI C specifies as "undefined" almost any interaction with
> the world outside the signal handler except (a) calling signal() to reset
> that particular signal, and (b) assigning a variable to a flag of a specific
> (implementation-defined) type.  In particular, it is impossible to guarantee
> that longjmp() will work from within a signal handler, because there are
> machines where it won't.  This is really annoying in the presence of 4BSD's
> gratuitous breakage of the default semantics of signals, but there is
> nothing that can be done about it.

Is it allowed to ask for help?  :-)

Let me present a simple scenario.  I have a command line driven interactive
program.  I want to be able to give it an interrupt and have it respond by
aborting the processing in the current command and returning control to the
main command loop (read/interpret/execute).  Since the interrupt can come
in the middle of a data structure manipulation I have carefully (I hope)
defined safe and unsafe states.  At the beginning of an unsafe section
of code I set a flag; at the end I lift it.  The handler checks whether
the flag is set; if it is not it does a longjmp.  If the flag is set the
handler sets another flag which is checked by the "unprotect" code which
does the longjmp.  I haven't seen any problems with this under SUN 3,
SUN 4, AIX, AUX, COFF, MIPS, ULTRIX, Concurrent, Apollo, and some others
which I forget off hand.  Maybe I've been lucky!  Is this a kludge?
What is the right way to do this, if any.  Here is some representative
code:

inthndler () {
	extern int interrupt;
	extern int protection;
	extern jmp_buf csienv;

	signal(SIGNINT,SIG_IGN);
	interrupt = 1;
	if (!protection) longjmp(csienv,1);
	}

.... schematic main loop ....

	while (more) {
		setjmp(csienv);
		if (interrupt) {
			signal(SIGINT,SIG_IGN);
			... sundry cleanup ...
			interrupt = 0;
			signal(SIGINT,inthndlr);
			}
		... main loop body ...
		}

.... and the macros for delimiting 'unsafe' code ....

#define PROTECT {extern int protection;protection = 1;}

#define UNPROTECT {extern int protection;\
	extern int interrupt;\
	protection = 0;\
	if (interrupt) inthndlr();}
 
[Before anyone says RTFM, believe me, I have RTFM -- a number of them.]
Mostly I can puzzle these things out, but the rules for manipulating
signal and setjmp/longjmp are somewhat obscure.  From what Henry is
saying I infer that the above scheme is not quite legitimate.  I am
quite willing to believe that it is a total crock.  However I have to
admit that I neither am sure that the above scheme is bona fide (and
portable) nor, if it is not, how one does it right.
-- 
Richard Harter, Software Maintenance and Development Systems, Inc.
Net address: jjmhome!smds!rh Phone: 508-369-7398 
US Mail: SMDS Inc., PO Box 555, Concord MA 01742
This sentence no verb.  This sentence short.  This signature done.



More information about the Comp.lang.c mailing list