[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

@ -21,22 +21,27 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#define IO_STDERR_OK 0x0010
#if MK_OS_VMS || MK_OS_DOS
# define check_io_state() (IO_STDIN_OK|IO_STDOUT_OK|IO_STDERR_OK)
# define fd_inherit(_i) (0)
# define fd_noinherit(_i) (0)
# define fd_set_append(_i) (void)(0)
# define os_anontmp() (-1)
# define check_io_state() (IO_STDIN_OK|IO_STDOUT_OK|IO_STDERR_OK)
# define fd_inherit(_i) (0)
# define fd_noinherit(_i) (0)
# define fd_set_append(_i) (-1)
# define fd_reset_append(_i,_f) (void)(0)
# define os_anontmp() (-1)
#else
/* Determine the state of stdin/stdout/stderr. */
unsigned int check_io_state (void);
/* Set a file descriptor to close/not close in a subprocess. */
void fd_inherit (int);
void fd_noinherit (int);
void fd_inherit (int fd);
void fd_noinherit (int fd);
/* If the file descriptor is for a file put it into append mode. */
void fd_set_append (int);
/* If the file descriptor is for a file put it into append mode.
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. */
int os_anontmp (void);

View file

@ -318,6 +318,9 @@ output_dump (struct output *out)
#endif /* NO_OUTPUT_SYNC */
static int stdout_flags = -1;
static int stderr_flags = -1;
void
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
parallel jobs won't lose output due to overlapping writes. */
fd_set_append (fileno (stdout));
fd_set_append (fileno (stderr));
stdout_flags = fd_set_append (fileno (stdout));
stderr_flags = fd_set_append (fileno (stderr));
}
void
@ -341,6 +344,8 @@ output_close (struct output *out)
{
if (stdio_traced)
log_working_directory (0);
fd_reset_append(fileno (stdout), stdout_flags);
fd_reset_append(fileno (stderr), stderr_flags);
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.
If it fails, just ignore it. */
void
int
fd_set_append (int fd)
{
int flags = -1;
#if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND)
struct stat stbuf;
int flags;
if (fstat (fd, &stbuf) == 0 && S_ISREG (stbuf.st_mode))
{
flags = fcntl (fd, F_GETFL, 0);
@ -845,6 +845,22 @@ fd_set_append (int fd)
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
}

View file

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