Email List: Xaustin-group-lX
[All Lists]

Interrupting shell sleep (was: enhancement to allow sub-second values)

To: austin-group-l@xxxxxxxxxxxxx
Subject: Interrupting shell sleep (was: enhancement to allow sub-second values)
From: Geoff Clare <gwc@xxxxxxxxxxxxx>
Date: Tue, 13 Jan 2009 11:03:16 +0000
References: <496C13F5.9040404@acm.org> <20090113042938.762952B21C3@mx5.roble.com> <496C20E6.2000404@acm.org>
Wayne Pollock <pollock@acm.org> wrote, on 13 Jan 2009:
>
> For example, another "sleep" utility issue is the way to wake
> up a process that is sleeping.  Any behavior is allowed and
> there is no way to reliably wake a script that is sleeping;
> sending SIGALRM may or may not wake this process.  (Korn
> shell can be interrupted this way, making it possible to have
> a script run a timed task.  Bash can't.)

In most shells, including ksh88 but not ksh93, sleep is not built-in
so the way to interrupt the sleep is to identify the PID of the sleep
process and terminate it (by sending SIGTERM).

In ksh93, sleep is built-in and, as you say, can be interrupted by
sending the shell a SIGALRM.  However, I would have thought this
was the more difficult case to handle.  How can you be sure the
shell is sleeping?  Even if you can be sure it is sleeping just
before you send the SIGALRM, you have a race condition: the sleep
could complete at the same time you send the SIGALRM.  With a separate
sleep process, this is no problem - your kill fails with ESRCH.  With
built-in sleep your SIGALRM might terminate the shell (unless you set
SIGALRM to be ignored, but in ksh93 that makes the sleep not be
interruptible with SIGALRM).

If you are writing a script which you want to be sure will have
interruptible sleeps regardless of which shell executes it, you can
force the use of a separate sleep process by means of a subshell.
I.e. execute sleep like this:

    (exec sleep 10)

instead of just:

    sleep 10

This should be usable for the case you mention (a timed task;
presumably with the task in the background, because if the sleep
was in the background it would have a separate PID anyway),
although it may be a little awkward to find the PID of the sleep.
Something like this should work:

pid=$(ps -o pid,ppid,comm |
      awk "\$2 == $$ && \$3 == \"sleep\" { print \$1 }")

-- 
Geoff Clare <g.clare@opengroup.org>
The Open Group, Thames Tower, Station Road, Reading, RG1 1LX, England

<Prev in Thread] Current Thread [Next in Thread>