Bug in sleep

utzoo!decvax!ucbvax!unix-wizards utzoo!decvax!ucbvax!unix-wizards
Sun Nov 15 23:26:37 AEST 1981


>From harpo!jerry at Berkeley Sun Nov 15 22:21:30 1981

Yes, an interrupt at an inoportune time could cause the V7 sleep to
"pause" forever.  It can be corrected (without kernel changes )
by making the following changes at two places. 
First at the point where pause is called: 

	wakecnt = 0 ;        /* Added. This is a new global (declared 
				static in this file) that will count how
				many times awake is called */

	alarm(sleep_tm);	    /* Unchanged */
	pause();		    /* Unchanged */
	unslept = alarm(0) ;        /* Unchanged */

	if ( unslept >= wakecnt ) unslept -= wakecnt ;
	else 			  unslept = 0 ;
		/* Added. Corrects for the effect of awake reseting the 
		   alarm. In normal circumstances unslept will
		   be at least one and wakecnt will be exactly
		   one so the test isn't required.  But that 
		   may not hold in some pathological cases. If
		   the else is taken some ticks will have been 
		   lost, but that's life. */

Second redefine awake:
	
    static 
    awake() {
	++ wakecnt ;
	signal(SIGALRM, awake ) ;
	alarm(1) ;
	}

I haven't tested this code, so it may not be right, but the idea is sound.
It adds two system calls for every invocation of sleep and so may not
be worth installing.  

Incidentally, there is another subtle bug in sleep.c.  It arises in
the following circumstance. Define
    
    caught() {
	< do whatever is to be done >
	signal(SIGALRM,caught) ;
	alarm(10) ;
	}

Somewhere else execute:

    signal(SIGALRM,caught) ; 
    alarm(10) ;
    sleep(20) ;

It's probably easier to avoid doing this sort of thing than to fix the
bug in sleep. If you really care, the problem is at the places where
signal(SIGALRM,alrm_sig) is called.

						    Jerry Schwarz
						    Bell Labs, Whippany



More information about the Comp.unix.wizards mailing list