Jim Meyering <[EMAIL PROTECTED]> writes: > It must be portable in practice. > There are tests of this behavior that are run as part of > coreutils' "make check" (see tests/help-version), so I doubt > we'll see any problem.
I'm a bit more cautious here. I think it's possible, for example, that if a program exits via exit(1), and the atexit handlers do their thing and closeout decides to exit with status 2, then the program might actually exit with status 1. The existing tests won't catch that, as I understand it. How about something like this change? It's simple, and it fixes the (perhaps-theoretical) problem. One price we pay is that you must be careful about the order of atexit calls, but coreutils already invokes atexit (close_stdout) first, so that won't be a problem for coreutils. Another price is that applications must flush their buffers before exiting, and should not use tmpfile, but coreutils already does that as well. 2006-07-21 Paul Eggert <[EMAIL PROTECTED]> * lib/closeout.c (close_stdout): Exit via _exit rather than exit, to avoid (possibly-theoretical) undefined behavior. Problem reported by Eric Blake. --- closeout.c.~1.19.~ 2006-02-07 16:04:23.000000000 -0800 +++ closeout.c 2006-07-21 09:42:25.000000000 -0700 @@ -25,6 +25,7 @@ #include <stdio.h> #include <stdbool.h> +#include <unistd.h> #include <errno.h> #include "gettext.h" @@ -93,9 +94,23 @@ close_stdout (void) write_error = _("write error"); if (file_name) - error (exit_failure, e, "%s: %s", quotearg_colon (file_name), + error (0, e, "%s: %s", quotearg_colon (file_name), write_error); else - error (exit_failure, e, "%s", write_error); + error (0, e, "%s", write_error); + + /* Since close_stdout is commonly registered via 'atexit', POSIX + and the C standard both say that 'exit' cannot be called + here, because the behavior is undefined if 'exit' is called + more than once. So call '_exit' instead of 'exit'. If + close_stdout is registered via atexit before other functions, + the other functions can act before this _exit is invoked. + + Applications that use close_stdout should flush stdio buffers + before exiting, since this call to _exit will bypass buffer + flushing. Applications should be doing that anyway, to check + for output errors. Also, these applications should not use + tmpfile, since _exit can bypass the removal of these files. */ + _exit (exit_failure); } }