Paul Eggert <eggert <at> CS.UCLA.EDU> writes: > > 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.
This is a behavior change - previously, you could use close_stdout outside of an atexit handler, and still have atexit handlers invoked on error. Should we document this change in the comment at the start of close_stdout (as opposed to inside the implementation body), stating that the recommended use is inside atexit? Also, should we make the closeout module depend on the atexit module? This also puts me in a bit of a dilemma with m4. I just proposed adding tmpfile_safer to solve m4's bug where tmpfile could capture stderr output. But using the closeout module would make this unsafe. It would be nice to have a drop-in streams-based temporary file replacement that worked nicely with the closeout module, perhaps as part of Bruno's proposed module for temporary files with clean removal on exit. A naive approach to safe tmp file removal is this, from m4's output.c: FILE * tmpfile (void) { char buf[32]; int fd; strcpy (buf, "/tmp/m4XXXXXX"); fd = mkstemp (buf); if (fd < 0) return NULL; unlink (buf); return fdopen (fd, O_BINARY ? "wb+" : "w+"); } However, POSIX allows unlink to fail if a file is in use, so coreutils's tac.c goes through some contortions when DONT_UNLINK_WHILE_OPEN is defined to register an atexit handler that closes the tmp file (although it also admits that there is a data race between the mkstemp and the eventual unlink; hopefully this is resolved by Bruno's module). -- Eric Blake