[comp.os.minix] POSIX sleep

tholm@uvicctr.UUCP (Terrence W. Holm) (10/26/88)

EFTH MINIX report #51  - October 1988 -  POSIX sleep(3)


The MINIX 1.3 sleep(3) does not handle alarm(2) pending
when sleep(3) is called. Nor does it return a correct
value. The following corrects these problems.

----------------------------------------------------------
echo x - sleep.3
gres '^X' '' > sleep.3 << '/'
XSUBROUTINES
X    sleep(3)		- suspend execution for awhile
X
XINVOCATION
X    unsigned sleep( secs )
X      unsigned secs;
X
XEXPLANATION
X    The process halts execution for <secs> seconds. It
X    will wake up early if any non-ignored signal occurs.
X
X    If an alarm(2) was already set then sleep(3) uses
X    the minimum of the time remaining and <secs> as the
X    sleep time. If the alarm(2) signal expires first, then
X    its handler is called and sleep(3) returns.
X
X    If an alarm(2) is still pending after sleep(3) completes,
X    then its time is adjusted by how long the process
X    really slept.
X
XRESULTS
X    Returns the number of seconds remaining until <secs>
X    should occur. This is non-zero when another signal woke
X    up sleep(3) early.
X
XREFERENCES
X    alarm(2), kill(2), pause(2), signal(2)
/
echo x - sleep.c
gres '^X' '' > sleep.c << '/'
X/*  sleep(3)
X *
X *  Sleep(n) pauses for 'n' seconds by scheduling an alarm interrupt.
X *
X *  Changed to conform with POSIX      Terrence W. Holm      Oct. 1988
X */
X
X#include <signal.h>
X
X
Xstatic _alfun()	/* Used with sleep() below */
X  {
X  }
X
X
Xunsigned sleep( secs )
X  unsigned secs;
X
X  {
X  unsigned current_secs;
X  unsigned remaining_secs;
X  void     (*old_signal)();
X
X  if ( secs == 0 )
X    return( 0 );
X
X  current_secs = alarm( 0 );   /*  Is there currently an alarm?  */
X
X  if ( current_secs == 0  ||  current_secs > secs )
X    {
X    old_signal = signal( SIGALRM, _alfun );
X
X    alarm( secs );
X    pause();
X    remaining_secs = alarm( 0 );
X
X    signal( SIGALRM, old_signal );
X
X    if ( current_secs > secs )
X	alarm( current_secs - ( secs - remaining_secs ) );
X
X    return( remaining_secs );
X    }
X
X
X  /*  current_secs <= secs,  ie. alarm should occur before secs  */
X
X  alarm( current_secs );
X  pause();
X  remaining_secs = alarm( 0 );
X
X  alarm( remaining_secs );
X
X  return( secs - ( current_secs - remaining_secs ) );
X  }
/
----------------------------------------------------------

		Terrence W. Holm
		  uw-beaver!uvicctr!tholm

n62@nikhefh.nikhef.nl (Klamer Schutte) (11/16/89)

Here is a POSIX implementation of sleep(3). 
Also are provided the POSIX signal routines. 

There are (minimal :-)) two bugs in the code:
- When implementing the posix-style signal routines in user code it is not
  possible to overcome the problem of two interrupts quickly after each other.
  When there is not enough time for another signal() call the default action
  will be taken.
- With the implementation of sleep is there a problem of a bad resolution of 
  alarm(2). Please look in the file sleep.c for the complete problem.

Please all try this code and report bugs.

I have not tried to implement the signal routines as kernel routines as that
has to wait for V2.0; this code is intended for V1.4?. 

Included are test routines for the code.

Klamer Schutte (.signature at end).
------------------------------------- cut here -----------------------------
echo x - Makefile
sed '/^X/s///' > Makefile << 'Shar_Of_Makefile_Eof'
X# Makefile for signal functions
X#
X# Klamer Schutte, 14/11/89
X
XSRC	= signal.c pos_signal.c sleep.c
X
XOBJ	= signal.o pos_signal.o sleep.o
X
XCFLAGS	= -DATARI_ST -DACK -I. -v 
X
X
Xall:	test1 test2 test3 test4
X
Xtest1:	${OBJ} test1.o
X	cc  -v -o $@ $<
X
Xtest2:	${OBJ} test2.o
X	cc  -v -o $@ $<
X
Xtest3:	${OBJ} test3.o
X	cc  -v -o $@ $<
X
Xtest4:	${OBJ} test4.o
X	cc  -v -o $@ $<
X
X${OBJ}:	signal.h
X
Shar_Of_Makefile_Eof
echo x - lib.h
sed '/^X/s///' > lib.h << 'Shar_Of_lib.h_Eof'
X#include <minix/const.h>
X#include <minix/type.h>
X#include <minix/callnr.h>
X#include <errno.h>
X
Xextern message M;
X
X#define MM                 0
X#define FS                 1
X
Xextern int callm1(), callm3(), callx(), len();
Xextern int errno;
Xextern void begsig();		/* interrupts all vector here */
Shar_Of_lib.h_Eof
echo x - pos_signal.c
sed '/^X/s///' > pos_signal.c << 'Shar_Of_pos_signal.c_Eof'
X/*
X *	pos_signal.c
X *
X *	Fake the POSIX 1003.1 1988 signal routines using the old V7 signal
X *	interface.
X *	The old signal() must be renamed to _signal(). Also must the function
X *	called by a signal have the signal number as an argument.
X *	A new signal() interface is also provided.
X *
X *	Bugs:
X *		Two signal send shortly after each other will still result in
X *		execution of the action associated with SIG_DFL.
X *
X *	Klamer Schutte, 14/11/89
X */
X
X#ifndef PRIVATE
X#define	PRIVATE	static
X#endif
X
X#include <signal.h>
X#include <setjmp.h>
X#include <errno.h>
X
Xextern void	(* _signal())();
X
X#ifndef NULL
X#define	NULL	0
X#endif
X
X#define	DIRTY_OK	/* define only if sigset_t is an integral type */
X
XPRIVATE jmp_buf	jmp_suspended;
X
XPRIVATE sigset_t	sig_blocked, sig_pending, sig_special;
X
XPRIVATE struct sigaction	sig_action[NR_SIGS+1];
X
XPRIVATE int	sig_special_case = 0;
X
XPRIVATE void	sys_called(), exec_func(), set_mask();
X
Xextern int
X	errno;
X
XPRIVATE void sys_called( nr )
Xint	nr;
X{
X   _signal( nr, sys_called );
X
X   if (sig_special_case)
X   {	if (!sigismember( &sig_special, nr ))
X	{	sig_special_case = 0;
X		exec_func( nr );
X		longjmp( jmp_suspended, 1 );
X	} else
X	{	sigaddset( &sig_pending, nr );
X		return;
X	}
X   }
X
X   if (sigismember( &sig_blocked, nr))	/* signal is blocked */
X   	sigaddset( &sig_pending, nr );
X   else
X   	exec_func( nr ); 
X}
X
XPRIVATE void exec_func( nr )
Xint	nr;
X{
X   sigset_t	old_set;
X   void		(* handler)();
X
X   sigprocmask( SIG_BLOCK, &sig_blocked, &old_set );
X   handler = sig_action[nr].sa_handler;
X   switch( (long) handler )
X   { case (long) SIG_IGN:	/* should only happen after init */
X	break;
X   case (long) SIG_DFL:
X	_signal( nr, SIG_DFL );
X	kill( getpid(), nr );
X	/* are there signals who's default action is ignore? */
X	_signal( nr, sys_called );
X	break;
X   default:
X   	(* handler)(nr);
X   }
X   sigprocmask( SIG_SETMASK, &old_set, (sigset_t *) NULL );
X}
X
Xsigset_t	sig_bits[] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 
X			0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000 };
X
Xint sigismember( sig_set, nr )
Xsigset_t	*sig_set;
Xint	nr;
X{
X	if ((nr<=0) || (nr>NR_SIGS))
X	{	errno = EINVAL;
X		return -1;
X	}
X
X	return (*sig_set & sig_bits[nr] ? 1 : 0);
X}
X
Xint sigdelset( sig_set, nr )
Xsigset_t	*sig_set;
Xint	nr;
X{
X	if ((nr<=0) || (nr>NR_SIGS))
X	{	errno = EINVAL;
X		return -1;
X	}
X
X	*sig_set &= ~(sig_bits[nr]);
X	
X	return 0;
X}
X
Xint sigaddset( sig_set, nr )
Xsigset_t	*sig_set;
Xint	nr;
X{
X	if ((nr<=0) || (nr>NR_SIGS))
X	{	errno = EINVAL;
X		return -1;
X	}
X
X	*sig_set |= sig_bits[nr];
X	
X	return 0;
X}
X
Xint sigemptyset( set )
Xsigset_t	*set;
X{
X	*set = 0;
X
X	return 0;
X}
X
Xint sigfillset( set )
Xsigset_t	*set;
X{
X	*set = ~0;
X
X	return 0;
X}
X
XPRIVATE int	sigs_inited = 0;
X
XPRIVATE init_sigs()
X{	
X   int	i;
X
X   sigemptyset( &sig_pending );
X   sig_blocked = sig_pending;
X   for(i=1;i<=NR_SIGS;i++)
X   {	sigemptyset( &(sig_action[i].sa_mask) );
X	sig_action[i].sa_flags = 0;
X	sig_action[i].sa_handler = _signal( i, sys_called );
X	if (sig_action[i].sa_handler == SIG_IGN)
X		_signal( i, SIG_IGN );
X   }
X   sigs_inited = 1;
X}
X
Xint sigaction( sig, act, oact )
Xint	sig;
Xstruct sigaction	*act, *oact;
X{
X	/* before the first use the whole set must be inited */
X	if (!sigs_inited)
X		init_sigs();
X
X	if ((sig<=0) || (sig>NR_SIGS))
X	{	errno = EINVAL;
X		return -1;
X	}
X
X	if (oact != (struct sigaction *) NULL)
X		*oact = sig_action[sig];
X
X	if (act != (struct sigaction *) NULL)
X	{	if (act->sa_handler == SIG_IGN)
X			_signal( sig, SIG_IGN );
X		else
X			if (sig_action[sig].sa_handler == SIG_IGN)
X				_signal( sig, sys_called );
X		sig_action[sig] = *act;
X	}
X
X	return 0;
X}
X
Xint sigprocmask( how, set, oset )
Xint	how;
Xsigset_t	*set, *oset;
X{
X   sigset_t	tmp_set;
X#ifndef	DIRTY_OK
X   int	i;
X#endif
X
X   /* before the first use the whole set must be inited */
X   if (!sigs_inited)
X	init_sigs(); 
X
X
X   if (oset != (sigset_t *) NULL)
X	*oset = sig_blocked;
X
X   if (set != (sigset_t *) NULL)
X	switch( how )
X	{ case SIG_BLOCK:
X#ifdef	DIRTY_OK
X		sig_blocked |= *set;			
X		break;
X	case SIG_UNBLOCK:
X		tmp_set = sig_blocked & ~(*set);
X		set_mask( &tmp_set );
X#else
X   		for(i=1;i<=NR_SIGS;i++)
X			if (sigismember( &(set), i ) == 1)
X				sigaddset( &sig_blocked, i );
X		break;
X	case SIG_UNBLOCK:
X   		for(i=1;i<=NR_SIGS;i++)
X			if (sigismember( &(set), i ) == 0)
X			{	sigdelset( &sig_blocked, i );
X				exec_func( i );
X			}
X#endif
X		break;
X	case SIG_SETMASK:
X		set_mask( set );
X		break;
X	default:
X		errno = EINVAL;
X		return -1;
X	}
X
X   return 0;
X}
X		
XPRIVATE void set_mask( set )
Xsigset_t	*set;
X{
X	int	i;
X
X   for(i=1;i<=NR_SIGS;i++)
X	if ((!sigismember( set, i )) && sigismember( &sig_pending, i ))
X	{	sigdelset( &sig_pending, i );
X		exec_func( i );
X	}
X   sig_blocked = *set;
X}
X
Xint sigpending( set )
Xsigset_t	*set;
X{
X   if (!sigs_inited)
X	init_sigs(); 
X
X
X   *set = sig_pending;
X
X   return 0;
X}
X
Xint sigsuspend( sigmask )
Xsigset_t	*sigmask;
X{
X   sigset_t	old;
X   int		res;
X
X   if (!sigs_inited)
X	init_sigs(); 
X
X   old = sig_blocked;
X   if ( setjmp( jmp_suspended ) == 0)
X   {	set_mask( sigmask );
X	sig_special = *sigmask;
X	sig_special_case = 1;
X	while(1)
X		pause();
X   }
X   set_mask( &old );
X
X   errno = EINTR;
X   return -1;
X}
X
X/* provide old V7 interface to signal function */
X
XPRIVATE void (*old_funcs[NR_SIGS+1])();
X
XPRIVATE void old_sig( nr )
Xint	nr;
X{
X   void	(*func)();
X
X   func = signal( nr, SIG_DFL );
X   switch((long)func)
X   { case (long) SIG_IGN:		/* should not happen after init */
X	break;
X   case (long) SIG_DFL:
X	_signal( nr, SIG_DFL );
X	kill( getpid(), nr );
X	/* are there signals who's default action is ignore? */
X	_signal( nr, sys_called );
X	break;
X   default:
X   	(* func)(nr);
X   }
X}
X   
Xvoid (*signal( sig, func))()
Xint	sig;
Xvoid	(*func)();
X{
X   struct sigaction	new;
X   void	(*old)();
X
X   new.sa_handler = old_sig;
X   sigemptyset( &(new.sa_mask) );
X   new.sa_flags = 0;
X   old = old_funcs[sig];
X   old_funcs[sig] = func;
X   sigaction( sig, &new, (struct sigaction *) NULL);
X   return old;
X}
X
X
Shar_Of_pos_signal.c_Eof
echo x - signal.c
sed '/^X/s///' > signal.c << 'Shar_Of_signal.c_Eof'
X#include "lib.h"
X#include <signal.h>
X
X/* ATTENTION: changed code but not comments to handler type (*void)() -- KS */
X
Xvoid (*vectab[NSIG])();	/* array of functions to catch signals */
X
X/* The definition of signal really should be 
X *  PUBLIC int (*signal(signr, func))()
X * but some compilers refuse to accept this, even though it is correct.
X * The only thing to do if you are stuck with such a defective compiler is
X * change it to
X *  PUBLIC int *signal(signr, func)
X * and change ../h/signal.h accordingly.
X */
X
XPUBLIC void (*_signal(signr, func))()
Xint signr;			/* which signal is being set */
Xvoid (*func)();			/* pointer to function that catches signal */
X{
X  int r;
X  void	(*old)(), begsig();
X
X  old = vectab[signr - 1];
X  vectab[signr - 1] = func;
X  M.m6_i1 = signr;
X  M.m6_f1 = ( (func == SIG_IGN || func == SIG_DFL) ? func : begsig);
X  r = callx(MM, SIGNAL);
X  if (r == 1)
X	old = SIG_IGN;
X  return( (r < 0 ? (void (*)()) r : old) );
X}
Shar_Of_signal.c_Eof
echo x - signal.h
sed '/^X/s///' > signal.h << 'Shar_Of_signal.h_Eof'
X/* 
X *	signal.h
X *
X *	original: minix-st distribution.
X *
X *	Changed signal handler type to (*void)()
X *	Added 	sigset_t
X *		struct sigaction 
X *		SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK
X *		SIGABRT, SIGUSR1, SIGUSR2
X *	for POSIX conformance.
X *	Added SIG_FL_DFL					KS 14/11/89
X */
X
X#define NSIG              16	/* number of signals used */
X
X#define	SIGHUP	           1	/* hangup */
X#define SIGINT             2	/* interrupt (DEL) */
X#define SIGQUIT            3	/* quit (ASCII FS) */
X#define SIGILL             4	/* illegal instruction (not reset when caught)*/
X#define SIGTRAP            5	/* trace trap (not reset when caught) */
X#define SIGIOT             6	/* IOT instruction */
X#define SIGEMT             7	/* EMT instruction */
X#define SIGFPE             8	/* floating point exception */
X#define SIGKILL            9	/* kill (cannot be caught or ignored) */
X#define SIGBUS            10	/* bus error */
X#define SIGSEGV           11	/* segmentation violation */
X#define SIGSYS            12	/* bad argument to system call */
X#define SIGPIPE           13	/* write on a pipe with no one to read it */
X#define SIGALRM           14	/* alarm clock */
X#define SIGTERM           15	/* software termination signal from kill */
X
X#define	SIGABRT		SIGIOT  /* Not normally used */
X#define SIGUSR1		SIGEMT  /* Not normally used */
X#define SIGUSR2		SIGSYS	/* Only used in very rare conditions */
X
X#define STACK_FAULT       16	/* used by kernel to signal stack fault */
X#define	NR_SIGS		NSIG
X
Xvoid	(*signal())();
X
Xtypedef	int	sigset_t;
X
Xstruct sigaction
X{  void	(* sa_handler)();
X   sigset_t	sa_mask;
X   int		sa_flags;	
X};
X
X/* Values for calling sigprocmask */
X#define	SIG_BLOCK	1
X#define	SIG_UNBLOCK	2
X#define	SIG_SETMASK	4
X
X#define	SIG_DFL	(void (*)())0
X#define	SIG_IGN	(void (*)())1
Shar_Of_signal.h_Eof
echo x - sleep.c
sed '/^X/s///' > sleep.c << 'Shar_Of_sleep.c_Eof'
X/*
X * 	sleep()	
X *
X *	POSIX compatible implementation		Klamer Schutte, 24/10/89
X *
X *	Using new (IEEE 1003.1 1988) signal routines	KS 15/11/89
X *
X * Bugs:
X *	The minix kernel doesn't give a precise info about the time the
X *	next alarm is scheduled. When the time to go is less than 1 second
X *	but bigger than 0 (i.e. there is a alarm) than alarm returnes 0.
X *	This means small alarms get lost.
X *	Fix: replace line 3160 in the book by:
X *  	  mc.SECONDS_LEFT = (rp->p_alarm == 0L ? 0 : 
X *				(rp->p_alarm - realtime + HZ - 1) / HZ;
X *	This will round the time up instead of down, thus avoiding the bug.
X *	(This kernel fix is not (yet) tested -- KS).
X */
X
X#include "lib.h"
X#include <signal.h>
X#include <sys/types.h>
X
X#ifndef NULL
X#define	NULL	(char *)0L
X#endif
X
XPRIVATE void alfun(nr)			/* used with sleep() below */
Xint	nr;
X{
X}
X
XPUBLIC int sleep(n)
Xunsigned int n;
X{
X/* sleep(n) pauses for 'n' seconds by scheduling an alarm interrupt. */
X  long		old_alarm;		/* save old alarm signal */
X  int		rest;
X  time_t	start;			/* time at start */
X
X  int		pending = 0, blocked = 0;
X  sigset_t	mask_alrm, no_mask, old_mask, pend;
X  struct sigaction	alfun_wrap, old_action;
X
X  if (n == 0)
X	return 0;			/* as in UNIX */
X  start = time( NULL );
X
X  /* get old signal state and block SIGALRM */
X  old_alarm = alarm( 0 );
X  sigemptyset( &mask_alrm );
X  sigaddset( &mask_alrm, SIGALRM );
X  sigprocmask( SIG_BLOCK, &mask_alrm, &old_mask );
X  if (sigismember( &old_mask, SIGALRM ))
X	blocked = 1;
X  sigpending( &pend );
X  if (sigismember( &pend, SIGALRM ))
X	pending = 1;
X
X  /* set up alfun */
X  alfun_wrap.sa_handler = alfun;
X  alfun_wrap.sa_flags = 0;
X  sigemptyset( &(alfun_wrap.sa_mask ) );
X  sigaction( SIGALRM, &alfun_wrap, &old_action );
X
X  if (pending)				/* if pending make unpending */
X  {	sigprocmask( SIG_UNBLOCK, &mask_alrm, (sigset_t *) NULL );	
X	sigprocmask( SIG_BLOCK, &mask_alrm, (sigset_t *) NULL );
X  }
X
X  no_mask = old_mask;
X  sigdelset( &no_mask, SIGALRM );
X  if ((!blocked) && old_alarm && (old_alarm <= n))
X  {
X	alarm((unsigned int) old_alarm);
X	sigaction( SIGALRM, &old_action, (struct sigaction *) NULL );
X	sigsuspend( &no_mask );		/* wait for alarm; call old handler */
X	sigprocmask( SIG_SETMASK, &old_mask, (sigset_t *) NULL );
X	rest = n - (unsigned int)(time(NULL) - start);
X	return (rest < 0 ? 0 : rest);
X  } 
X
X  alarm( n );
X  sigsuspend( &no_mask );
X  alarm( 0 );				/* reset alarm if still set */
X
X  /* reset signal state to original state */
X  sigaction( SIGALRM, &old_action, (struct sigaction *) NULL );
X
X  rest = (int)(time(NULL) - start);
X  if (old_alarm)
X  {	old_alarm -= rest;
X	/* old_alarm should be >= 0; when no big scheduler delays occur */
X  	if (old_alarm > 0)
X  	{	
X		alarm((unsigned int)old_alarm);
X  	} else
X		kill(getpid(),SIGALRM);
X  }
X  if (pending)
X	kill(getpid(), SIGALRM);
X  sigprocmask( SIG_SETMASK, &old_mask, (sigset_t *) NULL );
X  rest = n - rest;
X  return (rest < 0 ? 0 : rest);
X}
Shar_Of_sleep.c_Eof
echo x - test1.c
sed '/^X/s///' > test1.c << 'Shar_Of_test1.c_Eof'
X#include <signal.h>
X#include <stdio.h>
X#include <setjmp.h>
X
Xjmp_buf	save;
X
Xvoid	catch( nr )
X{
X	printf("Caught signal %d\n", nr );
X	signal( nr, catch );
X	longjmp( save, 1 );
X}
X
Xmain()
X{
X	signal( SIGALRM, catch );
X	signal( SIGINT, catch );
X	signal( SIGUSR1, catch );
X
X	while( 1 )
X	{	
X		alarm( 1 );
X		if (setjmp( save ))
X		{	printf("Escaped by setjmp\n");
X			continue;
X		}
X		printf("Going to sleep\n");
X		pause();
X		printf("Awake again!\n");
X	}
X}
Shar_Of_test1.c_Eof
echo x - test2.c
sed '/^X/s///' > test2.c << 'Shar_Of_test2.c_Eof'
X#include <signal.h>
X#include <stdio.h>
X
Xvoid	catch( nr )
X{
X	char	buf[80];
X	
X	sprintf(buf,"Caught signal %d\n", nr );
X	write(1, buf, strlen(buf) );
X}
X
Xmain()
X{
X	struct sigaction new;
X
X	sigemptyset(&new.sa_mask);
X	new.sa_flags = 0;
X	new.sa_handler = catch;
X	sigaction( SIGALRM, &new, (struct sigaction *)NULL );
X	sigaction( SIGINT, &new, (struct sigaction *)NULL );
X	sigaction( SIGUSR1, &new, (struct sigaction *)NULL );
X
X	while( 1 )
X	{	
X		alarm( 1 );
X		printf("%d Going to sleep\n", getpid());
X		pause();
X		printf("%d Awake again!\n", getpid());
X	}
X}
Shar_Of_test2.c_Eof
echo x - test3.c
sed '/^X/s///' > test3.c << 'Shar_Of_test3.c_Eof'
X#include <signal.h>
X#include <stdio.h>
X
Xvoid	catch( nr )
X{
X	char	buf[80];
X	sigset_t	pend;
X
X	sigpending( &pend );	
X	sprintf(buf,"Caught signal %d pending %x\n", nr, pend );
X	write(1, buf, strlen(buf) );
X}
X
Xmain()
X{
X	struct sigaction new;
X	sigset_t	sleep_mask;
X	int		i=10;
X
X	sigemptyset(&new.sa_mask);
X	new.sa_flags = 0;
X	new.sa_handler = catch;
X	sigaction( SIGALRM, &new, (struct sigaction *)NULL );
X	sigaction( SIGINT, &new, (struct sigaction *)NULL );
X	sigaction( SIGUSR1, &new, (struct sigaction *)NULL );
X
X	sigfillset( &sleep_mask );
X	sigdelset( &sleep_mask, SIGALRM );
X	while( i-- )
X	{	
X		alarm( 1 );
X		printf("%d Going to sleep\n", getpid());
X		pause();
X		printf("%d Awake again!\n", getpid());
X		alarm( 1 );
X		printf("Going to sigsuspend\n" );
X		sigsuspend( &sleep_mask );
X		printf("Returned from sigsuspend\n");
X	}
X}
Shar_Of_test3.c_Eof
echo x - test4.c
sed '/^X/s///' > test4.c << 'Shar_Of_test4.c_Eof'
X/* test for sleep */
X#include <stdio.h>
X#include <signal.h>
X
Xvoid catch(nr)
Xint 	nr;
X{
X	char	buf[80];
X
X	sprintf(buf, "Caught signal %d\n", nr );
X	write( 1, buf, strlen(buf) );
X}
X
Xint	r;
Xstatic sigset_t	blocked;
Xstatic struct sigaction state;
X
X#define	Sleep(xxx) printf("Going to sleep %d sec.\n", xxx );		\
X		r = sleep( xxx );					\
X		printf("Result of sleep(%d) = %d\n", xxx, r ); 		\
X	     /*	sigprocmask(SIG_SETMASK,(sigset_t *)NULL,&blocked);	\
X		printf("Left blocked to be %x\n", blocked );		\
X		sigaction(SIGALRM, (struct sigaction *)NULL, &state ); 	\
X		printf("handler %lx\n", state.sa_handler );		*/
X
X#define	Alarm(x)	printf("Setting alarm to %d sec.\n", x );	\
X			alarm( x );
X
Xmain()
X{
X	struct sigaction	act;
X
X	Sleep(1);
X	Sleep(0);
X
X	act.sa_handler = catch;
X	sigemptyset( &(act.sa_mask));
X	act.sa_flags = 0;
X	sigaction(SIGALRM, &act, (struct sigaction *)NULL );
X	sigaction(SIGINT, &act, (struct sigaction *)NULL );
X	
X	Sleep( 1 );
X
X	Alarm( 2 );
X	Sleep( 4 );
X
X	Alarm( 6 );
X	Sleep( 2 );
X	Sleep( 10 );
X
X	Alarm( 5 );
X	Sleep( 2 );
X	Sleep( 10 );
X
X	Alarm( 4 );
X	Sleep( 2 );
X	Sleep( 10 );
X
X	Alarm( 3 );
X	Sleep( 2 );
X	Sleep( 10 );
X
X	Sleep( 10 );
X}
Shar_Of_test4.c_Eof
-- 
_____________________Yes, mail address changed again :-(________________________
Klamer Schutte        mcvax!nikhefh!{n62,Schutte}        {Schutte,n62}@nikhef.nl