[glib/th/gspawn-no-safe-close: 4/4] gspawn: avoid race due to retry with EINTR on close()
- From: Thomas Haller <thaller src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/th/gspawn-no-safe-close: 4/4] gspawn: avoid race due to retry with EINTR on close()
- Date: Tue, 18 Oct 2022 07:01:06 +0000 (UTC)
commit afa66d58934f28017e09487bd3d382ce1b273ff4
Author: Thomas Haller <thaller redhat com>
Date: Wed Oct 12 23:30:37 2022 +0200
gspawn: avoid race due to retry with EINTR on close()
Retry on EINTR is wrong on many OS, including Linux. See the comment
in _g_safe_close_with_error() why that is.
As we cannot use g_close() after fork, we had safe_close(). This had the
wrong retry loop on EINTR. Drop that.
This was especially problematic since commit 6f46294227f8 ('gspawn: Don’t
use g_close() in async-signal-safe context'). Before, safe_close() was
only called after fork, where there is only one thread and there is no
concern about a race.
Replace safe_close() with _g_safe_close() which gets all the things
right, including the (not) handling of EINTR, the ignoring of any other
error, being async-signal-safe (aside assertion failures for EBADF).
Fixes: 6f46294227f8 ('gspawn: Don’t use g_close() in async-signal-safe context')
glib/gspawn.c | 29 ++++++-----------------------
1 file changed, 6 insertions(+), 23 deletions(-)
---
diff --git a/glib/gspawn.c b/glib/gspawn.c
index 4e029eedf5..b748cc9fe5 100644
--- a/glib/gspawn.c
+++ b/glib/gspawn.c
@@ -58,6 +58,7 @@
#include "gthread.h"
#include "gtrace-private.h"
#include "glib/gstdio.h"
+#include "gutilsprivate.h"
#include "genviron.h"
#include "gmem.h"
@@ -162,8 +163,6 @@ extern char **environ;
*/
-static gint safe_close (gint fd);
-
static gint g_execute (const gchar *file,
gchar **argv,
gchar **argv_buffer,
@@ -267,11 +266,9 @@ close_and_invalidate (gint *fd)
{
if (*fd < 0)
return;
- else
- {
- safe_close (*fd);
- *fd = -1;
- }
+
+ _g_safe_close (*fd);
+ *fd = -1;
}
/* Some versions of OS X define READ_OK in public headers */
@@ -1338,27 +1335,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_safe_close (fd);
return 0;
}
@@ -1453,7 +1436,7 @@ safe_fdwalk (int (*cb)(void *data, int fd), void *data)
}
}
- safe_close (dir_fd);
+ _g_safe_close (dir_fd);
return res;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]