mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-03-27 18:10:03 +01:00
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:
commit
957679f024
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
@ -1766,24 +1767,38 @@ g_close (gint fd,
|
|||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
{
|
||||||
|
int errsv = errno;
|
||||||
|
|
||||||
|
if (errsv == EINTR)
|
||||||
|
{
|
||||||
/* Just ignore EINTR for now; a retry loop is the wrong thing to do
|
/* 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
|
* on Linux at least. Anyone who wants to add a conditional check
|
||||||
* for e.g. HP-UX is welcome to do so later...
|
* 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
|
* http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
|
||||||
* https://bugzilla.gnome.org/show_bug.cgi?id=682819
|
* https://bugzilla.gnome.org/show_bug.cgi?id=682819
|
||||||
* http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
|
* http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
|
||||||
* https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
|
* https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
|
||||||
*/
|
*/
|
||||||
if (G_UNLIKELY (res == -1 && errno == EINTR))
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
else if (res == -1)
|
}
|
||||||
|
|
||||||
|
if (error)
|
||||||
{
|
{
|
||||||
int errsv = errno;
|
|
||||||
g_set_error_literal (error, G_FILE_ERROR,
|
g_set_error_literal (error, G_FILE_ERROR,
|
||||||
g_file_error_from_errno (errsv),
|
g_file_error_from_errno (errsv),
|
||||||
g_strerror (errsv));
|
g_strerror (errsv));
|
||||||
|
}
|
||||||
|
|
||||||
errno = errsv;
|
errno = errsv;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user