On Sun, Jul 3, 2011 at 5:36 PM, Bruno Haible <br...@clisp.org> wrote: > 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].
Report to vger al viro and alan cox have fixed problem like this sometime ago. It is considered backported to stable > 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> > >