Path: utzoo!mnetor!uunet!lll-winken!lll-lcc!ames!ucsd!sdcc6!ix426 From: ix426@sdcc6.ucsd.EDU (Tom Stockfisch) Newsgroups: comp.lang.c Subject: Re: longjmp() from nested signal handlers Message-ID: <3669@sdcc6.ucsd.EDU> Date: 6 Apr 88 04:32:54 GMT References: <4548@june.cs.washington.edu> <26739@amdahl.uts.amdahl.com> Reply-To: ix426@sdcc6.ucsd.edu.UUCP (Tom Stockfisch) Organization: University of California, San Diego Lines: 86 In article <26739@amdahl.uts.amdahl.com> nw@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\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@chem.ucsd.edu