Path: utzoo!mnetor!uunet!lll-winken!lll-tis!ames!amdahl!nw From: nw@amdahl.uts.amdahl.com (Neal Weidenhofer) Newsgroups: comp.lang.c Subject: Re: longjmp() from nested signal handlers Message-ID: <28177@amdahl.uts.amdahl.com> Date: 15 Apr 88 00:55:57 GMT References: <4548@june.cs.washington.edu> <26739@amdahl.uts.amdahl.com> <3669@sdcc6.ucsd.EDU> Organization: Amdahl Corporation, Sunnyvale CA Lines: 81 Summary: Your solution would probably work, but... In article <3669@sdcc6.ucsd.EDU>, ix426@sdcc6.ucsd.EDU (Tom Stockfisch) writes: > 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 point is that this has ALWAYS been true. If you (permanently) exit a subroutine in a random place, global and/or static variables may be left in an inconsistent state so that future use of routines that depend on those variables may fail in mysterious ways. The fact that it hasn't happend to you yet only means that it works most of the time, not that it's correct. > 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. Yes, this can be a problem on some architectures. You may have to choose the lesser of two evils (which, as some friends of mine are fond of pointing out, is still evil.) > >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: [Long example deleted.] This example will probably work, provided that you identify ALL instances of vulnerable code. Note that it works by having the signal handler just set a flag most of the time anyway. Consider the problem faced by X3J11 though. It's our job to specify the language in such a way that conforming programs will ALWAYS work on conforming implementations. There is just no way that a language standard could specify a scheme such as this and when it needs to be used. > >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. The kernel is typically protected by the hardware delaying some or all interrupts until the kernel returns control to the user. For a library routine though, stop and think for a moment. How would you accomplish it? > || Tom Stockfisch, UCSD Chemistry tps@chem.ucsd.edu The opinions expressed above are mine (but I'm willing to share.) Regards, Neal Weidenhofer Where have all the ...{hplabs|ihnp4|ames|decwrl}!amdahl!nw graveyards gone? Amdahl Corporation Gone to flowers every one. 1250 E. Arques Ave. (M/S 316) P. O. Box 3470 Sunnyvale, CA 94088-3470 (408)737-5007