[comp.unix.questions] Problem with sleep and signal/alarm.

winnard@frith.msu.edu (05/06/91)

I'm having trouble getting the sleep function to work
under C when I use signal/alarm function.  When the
signal/alarm call is taken out of the following code, the
program will print "Sleep 10..." then it will wait 10 seconds
before printing how long it did not sleep every time through the 
loop.  But with the signal/alarm function in place the sleep will 
return immediately and still indicate that it slept 10 seconds
every time through the loop.

#include <stdio.h>
#include <signal.h>
#include <errno.h>

main()
{
   int x;

   signal( SIGALRM, SIG_IGN );
   alarm( 1 );

   while( 1 )
   {
      printf("Sleep 10...");
      x = sleep( (unsigned)10 );
      if( x == -1 ) perror("");
      else printf("unslept %d\n", x );
   }
}

If you don't know why this is happening maybe you know a way 
to timeout a read function.  Either solution would be of great help.
Thanks.   
Jamie Winnard
winnard@frith.egr.msu.edu

rbart@shakespyr.Pyramid.COM (Bob Bart) (05/07/91)

In article <1991May6.153937.28635@msuinfo.cl.msu.edu>,
winnard@frith.msu.edu writes:
|> I'm having trouble getting the sleep function to work
|> under C when I use signal/alarm function.

The sleep() function uses the interval timer to do the sleep. This means you
can't use both simultaneously.

You can have your cake, but you can't eat it.

      -#-------  Bob Bart -  Performance Analyst                  415-335-8101
    ---###-----  Pyramid Technology Corporation          pyramid!pyrnova!rbart
  -----#####---  Mountain View, CA  94039            rbart@pyrnova.pyramid.com
-------#######-  U.S.A.

toma@swsrv1.cirr.com (Tom Armistead) (05/07/91)

In article <1991May6.153937.28635@msuinfo.cl.msu.edu> winnard@frith.msu.edu writes:
>I'm having trouble getting the sleep function to work
>under C when I use signal/alarm function.  When the
>signal/alarm call is taken out of the following code, the
>program will print "Sleep 10..." then it will wait 10 seconds
>before printing how long it did not sleep every time through the 
>loop.  But with the signal/alarm function in place the sleep will 
>return immediately and still indicate that it slept 10 seconds
>every time through the loop.
>
>#include <stdio.h>
>#include <signal.h>
>#include <errno.h>
>
>main()
>{
>   int x;
>
>   signal( SIGALRM, SIG_IGN );
>   alarm( 1 );
>
>   while( 1 )
>   {
>      printf("Sleep 10...");
>      x = sleep( (unsigned)10 );
>      if( x == -1 ) perror("");
>      else printf("unslept %d\n", x );
>   }
>}
>
>If you don't know why this is happening maybe you know a way 
>to timeout a read function.  Either solution would be of great help.
>Thanks.   
>Jamie Winnard
>winnard@frith.egr.msu.edu

sleep and alarm/signal processing are supposed to work in harmony, but I've
never been able to make that happend when the alarm/signal time was less than
the sleep time???   I would also be interested in why?

You can timeout a read() call by using alarm()/signal().  There is no need
for using sleep() (but I don't know your application, so how can I say that?).
You can also use ioctl() to setup your terminal to timeout between individual
characters (look at the ioctl(2) and termio(7) man pages - for (on Sys V)
~ICANON processing using VMIN and VTIME options).

I am assuming that you are reading from the keyboard?

Here is a brief example of how to use alarm() to interrupt a read from the
terminal.  Notice that the signal catching routine calls signal() to reinstall
itself (just in case you didn't know ;-) the SIGALRM signal (and most others)
is reset to SIG_DFL when caught).

========= ... ========================
#include <stdio.h>
#include <signal.h>
#include <errno.h>

void catch()			/* SIGALRM signal catching routine       */
{
    signal( SIGALRM, catch );	/* Need to re-install SIGALRM catcher    */
    alarm( 2 );			/* Reset to fire alarm in 2 more seconds */
    return;
}/*end catch*/

main()
{
    int timeout=0;
    char buf[BUFSIZ];

    signal( SIGALRM, catch );		/* Set signal catching routine      */

    buf[0] = '\0';			/* Empty data entry buffer          */

    printf( "Enter something: " );

    alarm( 2 );				/* Interrupt the gets in 2 seconds  */

    /************************************************************************
    ** gets() will return NULL if interrupted (by the SIGALRM).  You need to
    ** check for the EINTR errno (interrupted system call) also, because
    ** gets will also return NULL on end-of-file if no data has been entered.
    *************************************************************************/

    while( gets( buf ) == NULL &&	/* If no data from gets             */
		 errno == EINTR )	/* Because of an interrupt (alarm)  */
	if( ++timeout > 5 )		/* Wait 5 timeouts before giving up */
	    break;

    if( timeout > 5 )
	puts( "\nWhy didn't you enter anything?" );
}/*end main*/
========= ... ========================


Tom
-- 
Tom Armistead - Software Services - 2918 Dukeswood Dr. - Garland, Tx  75040
===========================================================================
toma@swsrv1.cirr.com                {egsner,letni,ozdaltx,void}!swsrv1!toma

les@chinet.chi.il.us (Leslie Mikesell) (05/08/91)

In article <1991May6.153937.28635@msuinfo.cl.msu.edu> winnard@frith.msu.edu () writes:
>I'm having trouble getting the sleep function to work
>under C when I use signal/alarm function.  When the
>signal/alarm call is taken out of the following code, the
>program will print "Sleep 10..." then it will wait 10 seconds
>before printing how long it did not sleep every time through the 
>loop.  But with the signal/alarm function in place the sleep will 
>return immediately and still indicate that it slept 10 seconds
>every time through the loop.
>   ...
>   signal( SIGALRM, SIG_IGN );
>   alarm( 1 );
>
>   while( 1 )
>   {
>      printf("Sleep 10...");
>      x = sleep( (unsigned)10 );

A couple of things:  First, the alarm granularity on unix is 1 second
intervals, so an alarm(1) will go off at the next second transition
after you do it which could be almost instantly.  Second, since sleep()
uses the same alarm signal to wake up, if your alarm goes off it will
reset the signal handler sleep() had installed.

>      if( x == -1 ) perror("");
>      else printf("unslept %d\n", x );
>   }
>}
>
>If you don't know why this is happening maybe you know a way 
>to timeout a read function.  Either solution would be of great help.

No need for the sleep(), just set up the alarm signal handler, do an
alarm(), and then read().  Under SysV, the read() will return with
an error, under BSD you have to longjmp() out of the signal handler.

Les Mikesell
  les@chinet.chi.il.us

pochmara@ogicse.ogi.edu (John Pochmara) (05/08/91)

In article <1991May07.221122.18325@chinet.chi.il.us> les@chinet.chi.il.us (Leslie Mikesell) writes:
>In article <1991May6.153937.28635@msuinfo.cl.msu.edu> winnard@frith.msu.edu () writes:
>No need for the sleep(), just set up the alarm signal handler, do an
>alarm(), and then read().  Under SysV, the read() will return with
>an error, under BSD you have to longjmp() out of the signal handler.

	You can also use sigpause(2) on BSD machines.

		--John
		  pochmara@cse.ogi.edu

torek@elf.ee.lbl.gov (Chris Torek) (05/09/91)

In article <1991May07.221122.18325@chinet.chi.il.us>
les@chinet.chi.il.us (Leslie Mikesell) writes:
>... First, the alarm granularity on unix is 1 second intervals, so
>an alarm(1) will go off at the next second transition after you do
>it which could be almost instantly.

Actually, this depends on your Unix variant.  There is still some
unavoidable jitter and delay, and adjtime() goofs things up, but in
general, on 4.2BSD systems and systems descended therefrom, the real
interval timer---alarm is a library function that this---really does
deliver SIGALRMs when you asked for them.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov

src@scuzzy.in-berlin.de (Heiko Blume) (05/09/91)

pochmara@ogicse.ogi.edu (John Pochmara) writes:
>	You can also use sigpause(2) on BSD machines.

or sigsuspend() on POSIXish boxes.
-- 
   Heiko Blume <-+-> src@scuzzy.in-berlin.de <-+-> (+49 30) 691 88 93 [voice!]
                  public UNIX source archive [HST V.42bis]:
        scuzzy Any ACU,f 38400 6919520 gin:--gin: nuucp sword: nuucp
                     uucp scuzzy!/src/README /your/home