Bourne | Ash |  #!  | find | ARG_MAX | Shells | whatshell | portability | permissions | UUOC | ancient | - | ../Various | HOME
"$@" | echo/printf | set -e | test | tty defs | tty chars | $() vs ) | IFS | using siginfo | nanosleep | line charset | locale


nanosleep(2) on Linux returns with EINTR after a SIGSTOP/SIGCONT

Should a SIGSTOP/SIGCONT be unnoticable for a process whenever possible?

Post scriptum: The problem with sleep(1) doesn't appear anymore since GNU sleep/core-utils 4.5.2


   linux$ sleep 100
   ^Z
   [1]+  Stopped                 sleep 100
   linux$ fg
   sleep 100
   linux$ echo $? # it terminated immediately.
   0

prolog: nanosleep(2) on Linux (at least 2.2, 2.4.20, glibc-2.1/2.2) returns with EINTR on a SIGCONT, after it got stopped by SIGSTOP.
(Or by SIGTSTP, a "tty-stop" which is used for job control in shells, e.g. <Ctrl-Z>. In contrast to STOP you can install a handler for TSTP).

climax: GNU sleep(1) uses sleep(3), which is implemented with nanosleep(2) in glibc-2.
But sleep(1) (version 1.16, 2.0) doesn't look at the return value from sleep(3).
And thus sleep(1) returns immediately, like it is illustrated at the head of this page.

One should keep in mind, that on other Unix flavours,

...return this way but just continue to sleep as expected.

By the way: Interestingly the sleep built-in of ksh93 is implemented with alarm(2) and thus handles the suspending properly.

One certainly might blame sleep(1) for not looking properly at sleep(3), but it is common practice to just use sleep(1) and expect a bit more robustness from sleep(3), it should not really fail on SIGCONT. Anyway, at the shell level you can't catch it, as sleep(1) returns "true" in this situation.

As far as I understand, the POSIX way is, that a system call should return with EINTR on SIGCONT only if a handler has been installed. But I am not yet that familiar with POSIX nanosleep specialities. nanosleep(2) is a socalled realtime function, which is complicating the situation.

Linux nanosleep(2) certainly does return the unslept time (call by reference), and so does GLIBC sleep(3), but I haven't found out yet, why sleep(3) must use nanosleep(2) at all. Several implementations use alarm(2) for example, which works quite well. If anybody knows about weird SIGALRM specialities, i'd really like to hear about it.

Apart from sleep(3), looking at nanosleep(2): Opinions are actually controverse on this, and the situation gets more complicated: While tracing a process, there is another system call, ptrace(PTRACE_SYSCALL|PTRACE_CONT, ...) that can wake up a process. This means that a debugger might not be transparent for a process which is using nanosleep(2) - probably a source for heisenbugs.


Meanwhile there was a short discussion on the austin-group list on opengroup.org, starting with
    From: "Michael T Kerrisk"
    To: The Austin Group
    Subject: Stop signals and interruption of system calls on Linux
    Date: Fri, 13 Feb 2004 11:44:50 +0100 (MET)
Selected mails: the question, a followup of the author and another answer


I had not been able to obtain a thread from comp.os.linux.development.system (Nov '98) from dejanews. Meanwhile google has incorporated their archive and I found it:

"nanosleep/sleep/SIGCONT bug", comp.os.linux.development.system (~7kB)

Some quotings from that thread:


  From: Linus Torvalds (torvalds@transmeta.com)

[...]

  > [...] the "nanosleep()" system call
  > by design simply is not restartable [...]

[...]

[sleep(3)]
  > The right thing to do is to _not_ use "nanosleep()" for sleeping, and
  > that requires a glibc change.

[...]

  > Alternatively, the interface to "nanosleep()" inside the kernel can be
  > completely revamped so that there is only one buffer that holds both the
  > incoming and the outgoing values, so that nanosleep can be restarted
  > with the proper timeout. 
  > 
  > For example, doing something like this is likely to be ok:
  > 
  >         nanosleep(&timespec, &timespec);
  > 
  > where the _modified_ timespec is required to be the _same_ as the
  > incoming timespec, and then you change "sys_nanosleep()" to do what the
  > original email in this thread suggested, ie make it return
  > -ERESTARTNOHAND.  Then it correctly handles the case of being restarted. 
  > 
  > But then it's not the POSIX nanosleep any more. 

I also concatenated together all articles from an according "Linux Kernel Archive" thread from Dec '99:
See "SIGCONT misbehaviour in Linux", ~40kB.
It seems two articles got lost in that digest, though.