summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2023-08-16 14:26:14 +0100
committerPhilip Withnall <philip@tecnocode.co.uk>2023-08-16 14:31:40 +0100
commitd0dc7171d64a74041555e850e95ac4965618405e (patch)
tree2d995eee729e967000d56c21c5d608da926eb3ca
parentde6cebb5f67577ddf438906d7cba7d62fb04631c (diff)
downloadglib-d0dc7171d64a74041555e850e95ac4965618405e.tar.gz
glib-unix: Accept O_CLOEXEC as well as FD_CLOEXEC in g_unix_open_pipe()
This is one step towards rectifying the mistake of using `FD_CLOEXEC` in the first place. Eventually we may deprecate support for `FD_CLOEXEC`, as the `O_*` flags better match the underlying `pipe()` API. See discussion on https://gitlab.gnome.org/GNOME/glib/-/merge_requests/3459#note_1779264 Signed-off-by: Philip Withnall <philip@tecnocode.co.uk>
-rw-r--r--glib/glib-unix.c24
-rw-r--r--glib/tests/unix.c29
2 files changed, 45 insertions, 8 deletions
diff --git a/glib/glib-unix.c b/glib/glib-unix.c
index 0532a500c..df5726cf0 100644
--- a/glib/glib-unix.c
+++ b/glib/glib-unix.c
@@ -82,15 +82,18 @@ g_unix_set_error_from_errno (GError **error,
* uses the pipe2() system call, which atomically creates a pipe with
* the configured flags.
*
- * As of GLib 2.78, the supported flags are `FD_CLOEXEC` and `O_NONBLOCK`. Prior
- * to GLib 2.78, only `FD_CLOEXEC` was supported — if you wanted to configure
- * `O_NONBLOCK` then that had to be done separately with `fcntl()`.
+ * As of GLib 2.78, the supported flags are `O_CLOEXEC`/`FD_CLOEXEC` (see below)
+ * and `O_NONBLOCK`. Prior to GLib 2.78, only `FD_CLOEXEC` was supported — if
+ * you wanted to configure `O_NONBLOCK` then that had to be done separately with
+ * `fcntl()`.
*
* It is a programmer error to call this function with unsupported flags, and a
* critical warning will be raised.
*
- * This function does not take `O_CLOEXEC`, it takes `FD_CLOEXEC` as if
- * for fcntl(); these are different on Linux/glibc.
+ * As of GLib 2.78, it is preferred to pass `O_CLOEXEC` in, rather than
+ * `FD_CLOEXEC`, as that matches the underlying `pipe()` API more closely. Prior
+ * to 2.78, only `FD_CLOEXEC` was supported. Support for `FD_CLOEXEC` may be
+ * deprecated and removed in future.
*
* Returns: %TRUE on success, %FALSE if not (and errno will be set).
*
@@ -101,11 +104,16 @@ g_unix_open_pipe (int *fds,
int flags,
GError **error)
{
- /* We only support FD_CLOEXEC and O_NONBLOCK */
- g_return_val_if_fail ((flags & (FD_CLOEXEC | O_NONBLOCK)) == flags, FALSE);
+ /* We only support O_CLOEXEC/FD_CLOEXEC and O_NONBLOCK */
+ g_return_val_if_fail ((flags & (O_CLOEXEC | FD_CLOEXEC | O_NONBLOCK)) == flags, FALSE);
+
+#if O_CLOEXEC != FD_CLOEXEC && !defined(G_DISABLE_CHECKS)
+ if (flags & FD_CLOEXEC)
+ g_debug ("g_unix_open_pipe() called with FD_CLOEXEC; please migrate to using O_CLOEXEC instead");
+#endif
if (!g_unix_open_pipe_internal (fds,
- (flags & FD_CLOEXEC) != 0,
+ (flags & (O_CLOEXEC | FD_CLOEXEC)) != 0,
(flags & O_NONBLOCK) != 0))
return g_unix_set_error_from_errno (error, errno);
diff --git a/glib/tests/unix.c b/glib/tests/unix.c
index 90345eda0..12f4a609f 100644
--- a/glib/tests/unix.c
+++ b/glib/tests/unix.c
@@ -58,6 +58,34 @@ test_pipe (void)
}
static void
+test_pipe_fd_cloexec (void)
+{
+ GError *error = NULL;
+ int pipefd[2];
+ char buf[1024];
+ gssize bytes_read;
+ gboolean res;
+
+ g_test_summary ("Test that FD_CLOEXEC is still accepted as an argument to g_unix_open_pipe()");
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/merge_requests/3459");
+
+ res = g_unix_open_pipe (pipefd, FD_CLOEXEC, &error);
+ g_assert (res);
+ g_assert_no_error (error);
+
+ g_assert_cmpint (write (pipefd[1], "hello", sizeof ("hello")), ==, sizeof ("hello"));
+ memset (buf, 0, sizeof (buf));
+ bytes_read = read (pipefd[0], buf, sizeof(buf) - 1);
+ g_assert_cmpint (bytes_read, >, 0);
+ buf[bytes_read] = '\0';
+
+ close (pipefd[0]);
+ close (pipefd[1]);
+
+ g_assert_true (g_str_has_prefix (buf, "hello"));
+}
+
+static void
test_pipe_stdio_overwrite (void)
{
GError *error = NULL;
@@ -472,6 +500,7 @@ main (int argc,
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/glib-unix/pipe", test_pipe);
+ g_test_add_func ("/glib-unix/pipe/fd-cloexec", test_pipe_fd_cloexec);
g_test_add_func ("/glib-unix/pipe-stdio-overwrite", test_pipe_stdio_overwrite);
g_test_add_func ("/glib-unix/error", test_error);
g_test_add_func ("/glib-unix/nonblocking", test_nonblocking);