[comp.unix.wizards] sleep

joel@intelisc.UUCP (Joel Clark) (05/19/88)

I was very interested in the recent disscussion of sleep(), PCATCH
and interrupts.  In brief:  

    1)	sleep(addr,j) with j < PZERO is uninterruptable.  

    2)	sleep(addr,j) with j > PZERO is interruptable with the sleep
	    immediately executing "longjmp(u.u_qsav);".  The user would
	    have an errno value EINTR for "interrupted system call", but
	    would continue executing.

    3)	sleep(addr,j) with j > PZERO and j | PCATCH is interruptable and
	    when interrupted will return 1 to the calling process.  This
	    allows the calling process to "cleanup (kernal data)" and
	    execute its own "longjmp(u.u_qsav)".

Right so far??

Questions:

	In #3 above what are the consequences of replacing the longjmp
	with a return?

	If the process in #2 or #3 above is running under a debugger,
	and the user types an interrupt (DEL, ^C, whatever), and then
	continues, and the debugger trys to continue the process by
	using ptrace(7, , ,0);,  why is the sleep interrupted?
	ptrace(7, , ,0) is supposed to continue the process with all
	pending signals deleted.
	
An example of this is to run sdb on the following program:

########################################################################
#include <fcntl.h>

main()
{
int fd,n;
char buf[100];

fd = open("/dev/tty",O_RDWR);
perror("sleep");
n = read(fd,buf,10);
perror("sleep2");
printf("Buf = %s\n",buf);
}
##########################################################################

After the first sleep message hit DEL.  The read system call will return
with a "Interrupted system call" message.

Though I cannot be sure that sdb is continuing with the 4th argument = 0,
the debugger I am having problems with is not sdb, and I am sure it is
using "ptrace(7, , ,0);"


I am using System V R3.0 for the 80386 as supplied by ATT.


Joel Clark
Intel Scientific Computers		joel@intelisc.uucp.com
Beaverton, OR  97006  USA		{tektronix}!ogcvax!intelisc!joel
(503) 629-7732

Intel Scientific accepts no liabilities from my statements here.

dave@lsuc.uucp (David Sherman) (09/29/88)

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?

David Sherman
The Law Society of Upper Canada
-- 
{ uunet!attcan  att  pyramid!utai  utzoo } !lsuc!dave

henry@utzoo.uucp (Henry Spencer) (09/30/88)

In article <1988Sep28.135914.25444@lsuc.uucp> dave@lsuc.uucp (David Sherman) writes:
>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.

Yup.  Sleep was a system call in V6, but in V7 it was superseded, in
theory, by alarm.

>No wonder I get funny interactions with my other uses of setjmp
>and SIGALRM.  I'm surprised some of it works at all.

The sleep code does make an attempt to preserve an existing alarm setting,
if any.
-- 
The meek can have the Earth;    |    Henry Spencer at U of Toronto Zoology
the rest of us have other plans.|uunet!attcan!utzoo!henry henry@zoo.toronto.edu

djones@megatest.UUCP (Dave Jones) (09/30/88)

From article <1988Sep28.135914.25444@lsuc.uucp), by dave@lsuc.uucp (David Sherman):
) 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.

The man-page on the Sun3 (BSD4.2 based) is explicit:

  sleep is implemented by setting an interval timer and  paus-
  ing  until  it expires.  The previous state of this timer is
  saved and restored. 

I would recommend that you process all signals, sleeps, selects, etc,
through a central location.  The "notifier" in Sun's sunview package
would suffice, but I don't know if its source is available.  In
any case, it should not be too difficult to implement it.

Good luck.

leo@philmds.UUCP (Leo de Wit) (09/30/88)

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.

peter@stca77.stc.oz (Peter Jeremy) (10/10/88)

In article <823@philmds.UUCP> leo@philmds.UUCP (Leo de Wit) writes:
>In article <1988Sep28.135914.25444@lsuc.uucp> dave@lsuc.uucp (David Sherman) writes:
>> [ Interactions between sleep(), SIGUSER, longjmp(), pause() ]
> [ isn't longjmp() ]
>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?

Looking at my XENIX system, sleep() will save and restore your alarm()
setting.  I did discover a bug with some of my code that used sleep(1)
for short timeouts - occasionally it would stop.  When I looked at sleep()
closely, I found that there is a hole between the alarm() and pause() calls
(about 20 usec on a 8MHz 80286 from memory) that would occasionally let the
alarm() timeout before it paused - hence the pause() waited until the next
signal.  A bit embarrasing...  I got around it by using nap() or longer
sleeps.  I suspect the bug exists in all library versions of sleep(), so
it may be worth checking if you use 'sleep(1);' at all.
-- 
Peter Jeremy (VK2PJ)         peter@stca77.stc.oz
Alcatel-STC Australia        ...!munnari!stca77.stc.oz!peter
41 Mandible St               peter%stca77.stc.oz@uunet.UU.NET
ALEXANDRIA  NSW  2015