[SV 65268] Un-set append mode for stdout/stderr on exit

It turns out that options set on stdout/stderr last after exit.
Leaving append-mode enabled can break other facilities, so reset the
flags on stdout/stderr before we exit.

* src/os.h: Add a new fd_reset_append() to reset flags on FDs.
Modify fd_set_append() to return the old flags.
* src/posixos.c (fd_reset_append): Set provided flags on the FD.
(fd_set_append): Return the previous flags set on the FD.
* src/output.c (output_init): Preserve old flags for stdout/stderr.
(output_close): Reset flags for stdout/stderr.
* src/w32/w32os.c: Implement dummy methods.
This commit is contained in:
Paul Smith 2024-03-24 15:19:11 -04:00
parent b8a2a4424b
commit 242603fa46
4 changed files with 46 additions and 15 deletions

View File

@ -24,7 +24,8 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
# define check_io_state() (IO_STDIN_OK|IO_STDOUT_OK|IO_STDERR_OK) # define check_io_state() (IO_STDIN_OK|IO_STDOUT_OK|IO_STDERR_OK)
# define fd_inherit(_i) (0) # define fd_inherit(_i) (0)
# define fd_noinherit(_i) (0) # define fd_noinherit(_i) (0)
# define fd_set_append(_i) (void)(0) # define fd_set_append(_i) (-1)
# define fd_reset_append(_i,_f) (void)(0)
# define os_anontmp() (-1) # define os_anontmp() (-1)
#else #else
@ -32,11 +33,15 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
unsigned int check_io_state (void); unsigned int check_io_state (void);
/* Set a file descriptor to close/not close in a subprocess. */ /* Set a file descriptor to close/not close in a subprocess. */
void fd_inherit (int); void fd_inherit (int fd);
void fd_noinherit (int); void fd_noinherit (int fd);
/* If the file descriptor is for a file put it into append mode. */ /* If the file descriptor is for a file put it into append mode.
void fd_set_append (int); Return the original flags for the file descriptor, or -1 if not found. */
int fd_set_append (int fd);
/* Reset the append mode to the flags returned by fd_set_append(). */
void fd_reset_append (int fd, int flags);
/* Return a file descriptor for a new anonymous temp file, or -1. */ /* Return a file descriptor for a new anonymous temp file, or -1. */
int os_anontmp (void); int os_anontmp (void);

View File

@ -318,6 +318,9 @@ output_dump (struct output *out)
#endif /* NO_OUTPUT_SYNC */ #endif /* NO_OUTPUT_SYNC */
static int stdout_flags = -1;
static int stderr_flags = -1;
void void
output_init (struct output *out) output_init (struct output *out)
{ {
@ -330,8 +333,8 @@ output_init (struct output *out)
/* Force stdout/stderr into append mode (if they are files) to ensure /* Force stdout/stderr into append mode (if they are files) to ensure
parallel jobs won't lose output due to overlapping writes. */ parallel jobs won't lose output due to overlapping writes. */
fd_set_append (fileno (stdout)); stdout_flags = fd_set_append (fileno (stdout));
fd_set_append (fileno (stderr)); stderr_flags = fd_set_append (fileno (stderr));
} }
void void
@ -341,6 +344,8 @@ output_close (struct output *out)
{ {
if (stdio_traced) if (stdio_traced)
log_working_directory (0); log_working_directory (0);
fd_reset_append(fileno (stdout), stdout_flags);
fd_reset_append(fileno (stderr), stderr_flags);
return; return;
} }

View File

@ -830,12 +830,12 @@ fd_noinherit (int fd)
/* Set a file descriptor referring to a regular file to be in O_APPEND mode. /* Set a file descriptor referring to a regular file to be in O_APPEND mode.
If it fails, just ignore it. */ If it fails, just ignore it. */
void int
fd_set_append (int fd) fd_set_append (int fd)
{ {
int flags = -1;
#if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND) #if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND)
struct stat stbuf; struct stat stbuf;
int flags;
if (fstat (fd, &stbuf) == 0 && S_ISREG (stbuf.st_mode)) if (fstat (fd, &stbuf) == 0 && S_ISREG (stbuf.st_mode))
{ {
flags = fcntl (fd, F_GETFL, 0); flags = fcntl (fd, F_GETFL, 0);
@ -845,6 +845,22 @@ fd_set_append (int fd)
EINTRLOOP(r, fcntl (fd, F_SETFL, flags | O_APPEND)); EINTRLOOP(r, fcntl (fd, F_SETFL, flags | O_APPEND));
} }
} }
#endif
return flags;
}
/* Reset a file descriptor referring to a regular file to be in O_APPEND mode.
If it fails, just ignore it. */
void
fd_reset_append (int fd, int flags)
{
#if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND)
if (flags >= 0)
{
int r;
EINTRLOOP(r, fcntl (fd, F_SETFL, flags));
}
#endif #endif
} }

View File

@ -512,10 +512,15 @@ fd_noinherit(int fd)
SetHandleInformation (fh, HANDLE_FLAG_INHERIT, 0); SetHandleInformation (fh, HANDLE_FLAG_INHERIT, 0);
} }
void int
fd_set_append (int fd UNUSED) fd_set_append (int fd UNUSED)
{} {
return -1;
}
void
fd_reset_append (int fd UNUSED, int flags UNUSED)
{}
HANDLE HANDLE
get_handle_for_fd (int fd) get_handle_for_fd (int fd)