Hi all, I wrote: > ... in programs that don't install signal handlers, EINTR ... also occurs in > MacOS X!
It is worse than that: 1) Even on Linux, even when the signal handlers have the SA_RESTART flag set, some system call (like msgrcv(), but not read()) can fail with EINTR. See [1]. 2) On all systems, when a signal handler has the SA_RESTART flag cleared, not only the read() system call will fail with EINTR, but also an fread() call will fail and set the stream's error bit. POSIX specifies it like this: [2] Test case: [3]. Run it, type Hello<Return> then Ctrl-C. Result is: $ ./a.out Hello ^CSIGINT! fread: Interrupted system call Hello Tested on Linux, MacOS X, FreeBSD, OpenBSD, AIX, HP-UX, IRIX, OSF/1, Solaris, Cygwin. 3) On MacOS X, SIGSTOP and SIGCONT make not only read() fail with EINTR, but fread() as well. Test case: [3]. Run it, type Hello<Return> then Ctrl-Z then fg. Result is: $ ./a.out Hello ^Z [1]+ Stopped ./a.out $ fg ./a.out fread: Interrupted system call Hello $ ./a.out --unbuffered Hello Hello ^Z [1]+ Stopped ./a.out --unbuffered $ fg ./a.out --unbuffered fread: Interrupted system call This was also reported in [4]. I would expect that EINTR also occurs in write() and fwrite() when writing to a pipe that is temporarily full, but I can't easily reproduce this. I think we need safe_fread() and safe_fgetc() functions. What do you think? Bruno [1] http://us.generation-nt.com/sigstop-interrupted-system-call-help-183657841.html [2] http://pubs.opengroup.org/onlinepubs/9699919799/functions/fread.html [3] ============================================================================= #include <errno.h> #include <signal.h> #include <stdio.h> #include <string.h> #include <unistd.h> static void handler (int sig) { write (1, "SIGINT!\n", 8); } int main (int argc, char *argv[]) { int unbuffered = (argc > 1 && strcmp (argv[1], "--unbuffered") == 0); signal (SIGINT, handler); siginterrupt (SIGINT, 1); for (;;) { char buf[4096]; size_t bufsize = (unbuffered ? 1 : sizeof (buf)); size_t count; errno = 0; count = fread (buf, 1, bufsize, stdin); if (count < bufsize && errno != 0) perror ("fread"); if (count > 0) fwrite (buf, 1, count, stdout); if (count < bufsize) break; } return 0; } ============================================================================= [4] http://factor-language.blogspot.com/2010/09/two-things-every-unix-developer-should.html -- In memoriam Yuri Shchekochikhin <http://en.wikipedia.org/wiki/Yuri_Shchekochikhin>