ksbszabo@wateng.UUCP (Kevin Szabo) (03/19/85)
In article <312@calgary.UUCP> radford@calgary.UUCP (Radford Neal) writes: >I think the moral of all this is: > - Don't use signal handlers if you can avoid it, especially for anything > other than printing an error message and exiting. > > - If you have to use signal handlers, you better think REALLY carefully > about what could happen, or you may write a program which fails > inexplicably once every few weeks. Your second moral should be applied BEFORE you apply the first moral. For instance, you can really confuse STDIO if you were to do the following in a signal handler: BadSignal( n ) { fprintf(stderr,"Huh? Caught unexpected signal %s!\n", list_of_sigs(n) ); } Stdio could have been in the middle of a malloc for flsbuf() or something. You could have gotten a core dump if you were unlucky enough... The problem is that practically none of STDIO is re-entrant. The only thing you can trust in a signal handler is a direct call to the kernel. Thus any printing in a signal handler should probably look like: (I might have the arguments in the wrong order to write() ) BadSignal( n ) { extern caught_signal; char *msg; msg = "Huh? ..."; while( *msg ) { if ( write( fileno(stderr), msg, 1 ) != 1 ) abort(); msg++; } ....spit out the rest of the message.... /* tell the rest of the program that a signal occurred. We'll * handle it outside of the signal handler because it is safer. * Multiple signals will get lost, but they usually do under UNIX * anyway */ caught_signal = n; } Note: The abort() is to get a core dump in case you have done something funny to stderr. You better not be catching SIGILL (or whatever abort causes) otherwise on some systems (4.2 BSD) you will just get an infinite loop. So maybe the first moral of the story is: don't do any more than set an external in a signal handler, otherwise be prepared to look long and hard at what you are doing. Kevin -- Kevin Szabo watmath!wateng!ksbszabo (U of Waterloo VLSI Group, Waterloo Ont.)