bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: closeout bug?


From: Paul Eggert
Subject: Re: closeout bug?
Date: Fri, 21 Jul 2006 09:43:18 -0700
User-agent: Gnus/5.1008 (Gnus v5.10.8) Emacs/21.4 (gnu/linux)

Jim Meyering <address@hidden> 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  <address@hidden>

        * 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);
     }
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]