[glib/wip/steal-fd] gmain: Add g_steal_fd() to API




commit 7f10bcc1b84e9ed6496569de741e84ff0e0a673c
Author: Simon McVittie <smcv collabora com>
Date:   Thu Feb 25 10:33:09 2021 +0000

    gmain: Add g_steal_fd() to API
    
    This is basically glnx_steal_fd() from libglnx. We already had two
    private implementations of it in GLib.
    
    Signed-off-by: Simon McVittie <smcv collabora com>

 docs/reference/glib/glib-sections.txt |  3 +++
 glib/gfileutils.c                     | 12 ++----------
 glib/gmain.c                          | 19 +++++++++++++++++++
 glib/gmain.h                          |  9 +++++++++
 glib/gspawn.c                         | 16 +++-------------
 glib/tests/mainloop.c                 | 30 ++++++++++++++++++++++++++++++
 6 files changed, 66 insertions(+), 23 deletions(-)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index 75994e889..c9697b45d 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -924,6 +924,9 @@ g_source_remove_by_user_data
 GClearHandleFunc
 g_clear_handle_id
 
+<SUBSECTION>
+g_steal_fd
+
 <SUBSECTION Private>
 GLIB_HAVE_ALLOCA_H
 alloca
diff --git a/glib/gfileutils.c b/glib/gfileutils.c
index a4e90265e..e0a2a65d0 100644
--- a/glib/gfileutils.c
+++ b/glib/gfileutils.c
@@ -1208,14 +1208,6 @@ write_to_file (const gchar  *contents,
   return TRUE;
 }
 
-static inline int
-steal_fd (int *fd_ptr)
-{
-  int fd = *fd_ptr;
-  *fd_ptr = -1;
-  return fd;
-}
-
 /**
  * g_file_set_contents:
  * @filename: (type filename): name of a file to write @contents to, in the GLib file name
@@ -1369,7 +1361,7 @@ g_file_set_contents_full (const gchar            *filename,
         }
 
       do_fsync = fd_should_be_fsynced (fd, filename, flags);
-      if (!write_to_file (contents, length, steal_fd (&fd), tmp_filename, do_fsync, error))
+      if (!write_to_file (contents, length, g_steal_fd (&fd), tmp_filename, do_fsync, error))
         {
           g_unlink (tmp_filename);
           retval = FALSE;
@@ -1479,7 +1471,7 @@ consistent_out:
         }
 
       do_fsync = fd_should_be_fsynced (direct_fd, filename, flags);
-      if (!write_to_file (contents, length, steal_fd (&direct_fd), filename,
+      if (!write_to_file (contents, length, g_steal_fd (&direct_fd), filename,
                           do_fsync, error))
         return FALSE;
     }
diff --git a/glib/gmain.c b/glib/gmain.c
index 15581ee7a..1bccd0f5a 100644
--- a/glib/gmain.c
+++ b/glib/gmain.c
@@ -6122,3 +6122,22 @@ g_get_worker_context (void)
 
   return glib_worker_context;
 }
+
+/**
+ * g_steal_fd:
+ * @fd_ptr: (not optional) (inout): A pointer to a file descriptor
+ *
+ * Sets @fd_ptr to `-1`, returning the value that was there before.
+ *
+ * Conceptually, this transfers the ownership of the file descriptor
+ * from the referenced variable to the caller of the function (i.e.
+ * ‘steals’ the reference). This is very similar to g_steal_pointer(),
+ * but for file descriptors.
+ *
+ * On POSIX platforms, this function is async-signal safe
+ * (see signal(7) and signal-safety(7)), making it safe to call from a
+ * signal handler or a #GSpawnChildSetupFunc.
+ *
+ * Returns: the value that @fd_ptr previously had
+ * Since: 2.70
+ */
diff --git a/glib/gmain.h b/glib/gmain.h
index 5c0e524cc..22ea17876 100644
--- a/glib/gmain.h
+++ b/glib/gmain.h
@@ -781,6 +781,15 @@ void     g_main_context_invoke      (GMainContext   *context,
                                      GSourceFunc     function,
                                      gpointer        data);
 
+GLIB_AVAILABLE_STATIC_INLINE_IN_2_70
+static inline int
+g_steal_fd (int *fd_ptr)
+{
+  int fd = *fd_ptr;
+  *fd_ptr = -1;
+  return fd;
+}
+
 /* Hook for GClosure / GSource integration. Don't touch */
 GLIB_VAR GSourceFuncs g_timeout_funcs;
 GLIB_VAR GSourceFuncs g_child_watch_funcs;
diff --git a/glib/gspawn.c b/glib/gspawn.c
index 95f5b868e..1acf24058 100644
--- a/glib/gspawn.c
+++ b/glib/gspawn.c
@@ -249,16 +249,6 @@ g_spawn_async (const gchar          *working_directory,
                                    error);
 }
 
-/* This function is called between fork() and exec() and hence must be
- * async-signal-safe (see signal-safety(7)). */
-static gint
-steal_fd (gint *fd)
-{
-  gint fd_out = *fd;
-  *fd = -1;
-  return fd_out;
-}
-
 /* Avoids a danger in threaded situations (calling close()
  * on a file descriptor twice, and another thread has
  * re-opened it since the first close)
@@ -2436,13 +2426,13 @@ success:
   close_and_invalidate (&stderr_pipe[1]);
 
   if (stdin_pipe_out != NULL)
-    *stdin_pipe_out = steal_fd (&stdin_pipe[1]);
+    *stdin_pipe_out = g_steal_fd (&stdin_pipe[1]);
 
   if (stdout_pipe_out != NULL)
-    *stdout_pipe_out = steal_fd (&stdout_pipe[0]);
+    *stdout_pipe_out = g_steal_fd (&stdout_pipe[0]);
 
   if (stderr_pipe_out != NULL)
-    *stderr_pipe_out = steal_fd (&stderr_pipe[0]);
+    *stderr_pipe_out = g_steal_fd (&stderr_pipe[0]);
 
   return TRUE;
 
diff --git a/glib/tests/mainloop.c b/glib/tests/mainloop.c
index d43b2cf08..d4531a731 100644
--- a/glib/tests/mainloop.c
+++ b/glib/tests/mainloop.c
@@ -21,6 +21,7 @@
  */
 
 #include <glib.h>
+#include <glib/gstdio.h>
 #include "glib-private.h"
 #include <stdio.h>
 #include <string.h>
@@ -2066,6 +2067,34 @@ test_maincontext_source_finalization_from_dispatch (gconstpointer user_data)
   g_main_context_unref (c);
 }
 
+static void
+test_steal_fd (void)
+{
+  GError *error = NULL;
+  gchar *tmpfile = NULL;
+  int fd = -42;
+  int borrowed;
+  int stolen;
+
+  g_assert_cmpint (g_steal_fd (&fd), ==, -42);
+  g_assert_cmpint (fd, ==, -1);
+  g_assert_cmpint (g_steal_fd (&fd), ==, -1);
+  g_assert_cmpint (fd, ==, -1);
+
+  fd = g_file_open_tmp (NULL, &tmpfile, &error);
+  g_assert_cmpint (fd, >=, 0);
+  borrowed = fd;
+  stolen = g_steal_fd (&fd);
+  g_assert_cmpint (fd, ==, -1);
+  g_assert_cmpint (borrowed, ==, stolen);
+
+  g_close (g_steal_fd (&stolen), &error);
+  g_assert_no_error (error);
+
+  g_assert_no_errno (remove (tmpfile));
+  g_free (tmpfile);
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -2111,6 +2140,7 @@ main (int argc, char *argv[])
   g_test_add_func ("/mainloop/unix-fd-priority", test_unix_fd_priority);
 #endif
   g_test_add_func ("/mainloop/nfds", test_nfds);
+  g_test_add_func ("/mainloop/steal-fd", test_steal_fd);
 
   return g_test_run ();
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]