Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!usc!zaphod.mps.ohio-state.edu!wuarchive!husc6!m2c!jjmhome!smds!rh From: rh@smds.UUCP (Richard Harter) Newsgroups: comp.lang.c Subject: Re: longjmp out of signal handler (was Re: alloca() portability) Summary: But how do you do it? Message-ID: <249@smds.UUCP> Date: 20 Nov 90 06:55:34 GMT References: <14377@smoke.brl.mil> <9122@ncar.ucar.edu> <27537@mimsy.umd.edu> <1990Nov16.181436.21736@zoo.toronto.edu> Organization: SMDS Inc., Concord, MA Lines: 76 In article <1990Nov16.181436.21736@zoo.toronto.edu>, henry@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.