sleep(3) uses longjmp and SIGALRM

Leo de Wit leo at philmds.UUCP
Fri Sep 30 09:18:18 AEST 1988


In article <1988Sep28.135914.25444 at lsuc.uucp> dave at 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.



More information about the Comp.unix.wizards mailing list