Merge branch 'th/gspawn-no-safe-close' into 'main'

gspawn: avoid race due to retry with EINTR on close()

See merge request GNOME/glib!2947
This commit is contained in:
Michael Catanzaro 2022-10-20 11:55:08 +00:00
commit 21a784920d
2 changed files with 21 additions and 27 deletions

View File

@ -162,8 +162,6 @@ extern char **environ;
*/ */
static gint safe_close (gint fd);
static gint g_execute (const gchar *file, static gint g_execute (const gchar *file,
gchar **argv, gchar **argv,
gchar **argv_buffer, gchar **argv_buffer,
@ -267,11 +265,9 @@ close_and_invalidate (gint *fd)
{ {
if (*fd < 0) if (*fd < 0)
return; return;
else
{ g_close (*fd, NULL);
safe_close (*fd); *fd = -1;
*fd = -1;
}
} }
/* Some versions of OS X define READ_OK in public headers */ /* Some versions of OS X define READ_OK in public headers */
@ -1338,27 +1334,13 @@ dupfd_cloexec (int old_fd, int new_fd_min)
return fd; return fd;
} }
/* This function is called between fork() and exec() and hence must be
* async-signal-safe (see signal-safety(7)). */
static gint
safe_close (gint fd)
{
gint ret;
do
ret = close (fd);
while (ret < 0 && errno == EINTR);
return ret;
}
/* This function is called between fork() and exec() and hence must be /* This function is called between fork() and exec() and hence must be
* async-signal-safe (see signal-safety(7)). */ * async-signal-safe (see signal-safety(7)). */
G_GNUC_UNUSED static int G_GNUC_UNUSED static int
close_func (void *data, int fd) close_func (void *data, int fd)
{ {
if (fd >= GPOINTER_TO_INT (data)) if (fd >= GPOINTER_TO_INT (data))
(void) safe_close (fd); g_close (fd, NULL);
return 0; return 0;
} }
@ -1453,7 +1435,7 @@ safe_fdwalk (int (*cb)(void *data, int fd), void *data)
} }
} }
safe_close (dir_fd); g_close (dir_fd, NULL);
return res; return res;
} }

View File

@ -1749,8 +1749,9 @@ g_utime (const gchar *filename,
* @fd: A file descriptor * @fd: A file descriptor
* @error: a #GError * @error: a #GError
* *
* This wraps the close() call; in case of error, %errno will be * This wraps the close() call. In case of error, %errno will be
* preserved, but the error will also be stored as a #GError in @error. * preserved, but the error will also be stored as a #GError in @error.
* In case of success, %errno is undefined.
* *
* Besides using #GError, there is another major reason to prefer this * Besides using #GError, there is another major reason to prefer this
* function over the call provided by the system; on Unix, it will * function over the call provided by the system; on Unix, it will
@ -1759,6 +1760,9 @@ g_utime (const gchar *filename,
* *
* It is a bug to call this function with an invalid file descriptor. * It is a bug to call this function with an invalid file descriptor.
* *
* Since 2.76, this function is guaranteed to be async-signal-safe if (and only
* if) @error is %NULL and @fd is a valid open file descriptor.
*
* Returns: %TRUE on success, %FALSE if there was an error. * Returns: %TRUE on success, %FALSE if there was an error.
* *
* Since: 2.36 * Since: 2.36
@ -1769,6 +1773,9 @@ g_close (gint fd,
{ {
int res; int res;
/* Important: if @error is NULL, we must not do anything that is
* not async-signal-safe.
*/
res = close (fd); res = close (fd);
if (res == -1) if (res == -1)
@ -1790,12 +1797,17 @@ g_close (gint fd,
return TRUE; return TRUE;
} }
g_set_error_literal (error, G_FILE_ERROR, if (error)
g_file_error_from_errno (errsv), {
g_strerror (errsv)); g_set_error_literal (error, G_FILE_ERROR,
g_file_error_from_errno (errsv),
g_strerror (errsv));
}
if (errsv == EBADF) if (errsv == EBADF)
{ {
/* There is a bug. Fail an assertion. Note that this function is supposed to be
* async-signal-safe, but in case an assertion fails, all bets are already off. */
if (fd >= 0) if (fd >= 0)
{ {
/* Closing an non-negative, invalid file descriptor is a bug. The bug is /* Closing an non-negative, invalid file descriptor is a bug. The bug is