Path: utzoo!attcan!uunet!mcvax!hp4nl!philmds!leo From: leo@philmds.UUCP (Leo de Wit) Newsgroups: comp.unix.wizards Subject: Re: sleep(3) uses longjmp and SIGALRM Message-ID: <823@philmds.UUCP> Date: 29 Sep 88 23:18:18 GMT References: <1988Sep28.135914.25444@lsuc.uucp> Reply-To: leo@philmds.UUCP (Leo de Wit) Organization: Philips I&E DTS Eindhoven Lines: 59 In article <1988Sep28.135914.25444@lsuc.uucp> dave@lsuc.uucp (David Sherman) writes: >I have a fairly complex CAI system that's used for legal education >here. It uses pipes, longjmp, SIGUSER and pause(2) to allow the student >to hit an interrupt key and change the level of instruction at any point. >It also uses sleep(3) here and there, and SIGALRM to log off idle users. >With all the various UNIXisms that interact, the programs occasionally >exhibit strange behaviour, which I'd never been able to pinpoint. > >Today someone asked me why sleep(3) is a library routine rather >than a system call, which I'd always thought it was. (This is a >v7-based UNIX, Perkin-Elmer's Edition VII.) So I read the code, >and was startled to find it uses SIGALRM and pause, with a longjmp >to put you back where you were. > >No wonder I get funny interactions with my other uses of setjmp >and SIGALRM. I'm surprised some of it works at all. > >The manual doesn't suggest sleep(3) shouldn't be used in conjunction >with setjmp or SIGALRM. But setjmp's certainly aren't nestable. >Has anyone else run into this issue? Comments? [The following may differ on various Unix systems, because also the system calls differ; I may also be imprecise about in which places exactly a system call or a library routine is used, but this doesn't affect the general idea. So no flames please! ] Talking about library routines: on Ultrix pause() is also a library routine (sigpause presumably being the underlying system call). Sleep() is implemented by setting a timer (setitimer(2) or alarm(3)) and waiting for the wake-up to occur; pause(3) or sigpause(2). Because the code of sleep() has to catch the SIGALRM it does a signal(3) or sigvec(). The reason a longjmp() is used at all here is perhaps that the system wil restart the system call (sigpause) if the interrupt handler just returns, which is not the intention of sleep(). Setjmp's not being nestable? Why should they not be? The tricky bit is you must use the correct jmpbuf with each setjmp(), and longjmp() back to the correct setjmp() (i.e. the code after it), but then it works OK. Since the library sleep() does a setjmp(), it will use its own private jmpbuf, and probably does a signal(SIGALRM,sighandler), where sighandler() is a function that will do the longjmp() back into sleep(), using the private jmpbuf as argument. No conflict with your jmpbuf(s). What may certainly cause you trouble is the setting of the alarm clock in sleep(); this will conflict with your setting of it, unless it is implemented clean enough to restore the original alarm time and setting of the interrupt handler. If it isn't, why not write your own? The strange behaviour of your programs may still have other causes. For instance, it is generally believed to be a bad idea to do a lot of stuff in interrupt handlers (you can get all kinds of trouble with interrupts interrupting interrupt handlers, restarting/not restarting interrupted system calls); this however is again Unix-type dependent. Perhaps you can be a bit more specific than just: strange behaviour? Leo.