Merge branch 'backport-2947-gspawn-eintr-glib-2-74' into 'glib-2-74'

Backport !2947 “gspawn: avoid race due to retry with EINTR on close()” to glib-2-74

See merge request GNOME/glib!2988
This commit is contained in:
Marco Trevisan 2022-10-21 15:59:59 +00:00
commit 957679f024
2 changed files with 36 additions and 39 deletions

View File

@ -162,8 +162,6 @@ extern char **environ;
*/
static gint safe_close (gint fd);
static gint g_execute (const gchar *file,
gchar **argv,
gchar **argv_buffer,
@ -267,11 +265,9 @@ close_and_invalidate (gint *fd)
{
if (*fd < 0)
return;
else
{
safe_close (*fd);
*fd = -1;
}
g_close (*fd, NULL);
*fd = -1;
}
/* 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;
}
/* 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
* async-signal-safe (see signal-safety(7)). */
G_GNUC_UNUSED static int
close_func (void *data, int fd)
{
if (fd >= GPOINTER_TO_INT (data))
(void) safe_close (fd);
g_close (fd, NULL);
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;
}

View File

@ -1749,8 +1749,9 @@ g_utime (const gchar *filename,
* @fd: A file descriptor
* @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.
* In case of success, %errno is undefined.
*
* Besides using #GError, there is another major reason to prefer this
* function over the call provided by the system; on Unix, it will
@ -1766,24 +1767,38 @@ g_close (gint fd,
GError **error)
{
int res;
res = close (fd);
/* Just ignore EINTR for now; a retry loop is the wrong thing to do
* on Linux at least. Anyone who wants to add a conditional check
* for e.g. HP-UX is welcome to do so later...
*
* http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
* https://bugzilla.gnome.org/show_bug.cgi?id=682819
* http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
* https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
/* Important: if @error is NULL, we must not do anything that is
* not async-signal-safe.
*/
if (G_UNLIKELY (res == -1 && errno == EINTR))
return TRUE;
else if (res == -1)
res = close (fd);
if (res == -1)
{
int errsv = errno;
g_set_error_literal (error, G_FILE_ERROR,
g_file_error_from_errno (errsv),
g_strerror (errsv));
if (errsv == EINTR)
{
/* Just ignore EINTR for now; a retry loop is the wrong thing to do
* on Linux at least. Anyone who wants to add a conditional check
* for e.g. HP-UX is welcome to do so later...
*
* https://lwn.net/Articles/576478/
* http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
* https://bugzilla.gnome.org/show_bug.cgi?id=682819
* http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
* https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
*/
return TRUE;
}
if (error)
{
g_set_error_literal (error, G_FILE_ERROR,
g_file_error_from_errno (errsv),
g_strerror (errsv));
}
errno = errsv;
return FALSE;
}