[net.unix-wizards] sub-second sleeps on BSD 4.2

friesen@psivax.UUCP (Stanley Friesen) (04/22/85)

	I am having trouble in writing a routine to handle less than
one second sleeps on BSD 4.2 using setitimer and sigpause. The routine
I am using is similar to the code for sleep().  My problem, it keeps
hanging sfter a random number of calls. It seems that eventually it
does not return from sigpause. Why? What can I do about it?
The code is as follows:

#include <sys/time.h> 
#include <signal.h>

int wakeup;

void nullfunc(){
    wakeup = 1;
}

struct itimerval tm = {{0, 0}, {0, 1500}};

delay()
{

    void nullfunc();

    signal(SIGALRM, nullfunc);
    wakeup = 0;
    if(setitimer(ITIMER_REAL, &tm, NULL)) exit(1);
    while(wakeup == 0) sigpause(0);
}
-- 

				Sarima (Stanley Friesen)

{trwrb|allegra|cbosgd|hplabs|ihnp4|aero!uscvax!akgua}!sdcrdcf!psivax!friesen
or {ttdica|quad1|bellcore|scgvaxd}!psivax!friesen

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (04/24/85)

> void nullfunc(){
>     wakeup = 1;
> }
> ...
>     signal(SIGALRM, nullfunc);
Sometimes the signal will fire HERE, ...
>     wakeup = 0;
>     if(setitimer(ITIMER_REAL, &tm, NULL)) exit(1);
>     while(wakeup == 0) sigpause(0);
... so you won't see it here.

The simplest way to get sub-second naps on 4.2BSD is to
do a select() specifying no file descriptors and a small timeout.

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (04/24/85)

> Sometimes the signal will fire HERE, ...
Oops, that was a bug on my part.  The following is still true:

> The simplest way to get sub-second naps on 4.2BSD is to
> do a select() specifying no file descriptors and a small timeout.

chris@umcp-cs.UUCP (Chris Torek) (04/25/85)

Your code is one big race condition.  If you aren't interested in
preserving the old interval timer, then use this (I've deleted the
unchanged code):

delay()
{
	int omask, nmask;
#define mask(x) (1 << ((x) - 1))

	signal(SIGALRM, nullfunc);
	wakeup = 0;
	omask = sigblock(mask(SIGALRM));
	nmask = omask & ~mask(SIGALRM);
	if (setitimer(ITIMER_REAL, &tm, (struct timeval *)NULL))
		exit(1);
	while (wakeup == 0)
		sigpause(nmask);
	sigsetmask(omask);
}

I'm assuming that sigpause() restores the signal mask that was in
effect before it's call; there is some very bogus-looking code in
the 4.2BSD kernel that is intended to do that, but I've never tested
it....
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 4251)
UUCP:	{seismo,allegra,brl-bmd}!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@maryland

donn@utah-gr.UUCP (Donn Seeley) (04/29/85)

This is another perennial question...  This time, though, I'll break
down and post my 'all-singing, all-dancing' fsleep() routine to
net.sources where everyone can beat on it.  fsleep() is the same as
sleep() but it takes a floating point argument instead of an integer
one.  I put some work into it trying to find all the race conditions
and timing problems but I still can't claim perfection for it;
corrections are welcomed...

Donn Seeley    University of Utah CS Dept    donn@utah-cs.arpa
40 46' 6"N 111 50' 34"W    (801) 581-5668    decvax!utah-cs!donn