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