diff options
author | Philip Withnall <philip@tecnocode.co.uk> | 2021-03-22 11:48:10 +0000 |
---|---|---|
committer | Philip Withnall <philip@tecnocode.co.uk> | 2021-03-22 11:48:10 +0000 |
commit | 01d1aaeb2744b6c4191a2a72d8e43c7c88aa7551 (patch) | |
tree | 3d8541ef65085a9b6c790103bb16b6b41faac9fb | |
parent | 46c34ea20fc020cde5d07c69747a5d4d12197e96 (diff) | |
parent | 6c5a227bcc7be280d3e59e6511bb4e67fe94dcb7 (diff) | |
download | glib-01d1aaeb2744b6c4191a2a72d8e43c7c88aa7551.tar.gz |
Merge branch 'wip/steal-fd' into 'master'
Add g_steal_fd() to API
See merge request GNOME/glib!1966
-rw-r--r-- | docs/reference/glib/glib-sections.txt | 3 | ||||
-rw-r--r-- | glib/gfileutils.c | 12 | ||||
-rw-r--r-- | glib/gmain.c | 20 | ||||
-rw-r--r-- | glib/gmain.h | 9 | ||||
-rw-r--r-- | glib/gspawn.c | 16 | ||||
-rw-r--r-- | glib/tests/mainloop.c | 32 |
6 files changed, 69 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..2e1ab3a25 100644 --- a/glib/gmain.c +++ b/glib/gmain.c @@ -6122,3 +6122,23 @@ 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)`](man:signal(7)) and + * [`signal-safety(7)`](man: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..e0ff04628 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,36 @@ 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); + g_assert_no_error (error); + 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_cmpint (stolen, ==, -1); + + g_assert_no_errno (remove (tmpfile)); + g_free (tmpfile); +} + int main (int argc, char *argv[]) { @@ -2111,6 +2142,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 (); } |