diff options
author | Thomas Haller <thaller@redhat.com> | 2023-03-28 14:38:08 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2023-05-17 07:59:17 +0200 |
commit | 55849fb5acff75bc2336db876d8883818903a625 (patch) | |
tree | 4494feb927935b5c9f239e6a553380f784a1d7c0 | |
parent | bbb40218fbbc686ee624dbb75d732fbd737cc608 (diff) | |
download | glib-55849fb5acff75bc2336db876d8883818903a625.tar.gz |
gmain: unify win/unix implementations for child watcher
Let's move the difference between the win/unix implementations closer to
where the difference is. Thereby, we easier see the two implementations
side by side. Splitting it at a higher layer makes the code harder to
read.
This is just a preparation for what comes next.
-rw-r--r-- | glib/gmain.c | 192 |
1 files changed, 92 insertions, 100 deletions
diff --git a/glib/gmain.c b/glib/gmain.c index b91e68d36..d50fd8315 100644 --- a/glib/gmain.c +++ b/glib/gmain.c @@ -488,6 +488,11 @@ static gboolean g_child_watch_dispatch (GSource *source, GSourceFunc callback, gpointer user_data); static void g_child_watch_finalize (GSource *source); + +#ifndef G_OS_WIN32 +static void unref_unix_signal_handler_unlocked (int signum); +#endif + #ifdef G_OS_UNIX static void g_unix_signal_handler (int signum); static gboolean g_unix_signal_watch_prepare (GSource *source, @@ -5479,17 +5484,49 @@ g_timeout_add_seconds_once (guint interval, /* Child watch functions */ -#ifdef G_OS_WIN32 +#ifdef HAVE_PIDFD +static int +siginfo_t_to_wait_status (const siginfo_t *info) +{ + /* Each of these returns is essentially the inverse of WIFEXITED(), + * WIFSIGNALED(), etc. */ + switch (info->si_code) + { + case CLD_EXITED: + return W_EXITCODE (info->si_status, 0); + case CLD_KILLED: + return W_EXITCODE (0, info->si_status); + case CLD_DUMPED: + return W_EXITCODE (0, info->si_status | WCOREFLAG); + case CLD_CONTINUED: + return __W_CONTINUED; + case CLD_STOPPED: + case CLD_TRAPPED: + default: + return W_STOPCODE (info->si_status); + } +} +#endif /* HAVE_PIDFD */ static gboolean g_child_watch_prepare (GSource *source, gint *timeout) { +#ifdef G_OS_WIN32 *timeout = -1; return FALSE; +#else /* G_OS_WIN32 */ + { + GChildWatchSource *child_watch_source; + + child_watch_source = (GChildWatchSource *) source; + + return g_atomic_int_get (&child_watch_source->child_exited); + } +#endif /* G_OS_WIN32 */ } -static gboolean +static gboolean g_child_watch_check (GSource *source) { GChildWatchSource *child_watch_source; @@ -5497,6 +5534,7 @@ g_child_watch_check (GSource *source) child_watch_source = (GChildWatchSource *) source; +#ifdef G_OS_WIN32 child_exited = child_watch_source->poll.revents & G_IO_IN; if (child_exited) @@ -5511,15 +5549,45 @@ g_child_watch_check (GSource *source) */ if (!GetExitCodeProcess (child_watch_source->pid, &child_status)) { - gchar *emsg = g_win32_error_message (GetLastError ()); - g_warning (G_STRLOC ": GetExitCodeProcess() failed: %s", emsg); - g_free (emsg); + gchar *emsg = g_win32_error_message (GetLastError ()); + g_warning (G_STRLOC ": GetExitCodeProcess() failed: %s", emsg); + g_free (emsg); - child_watch_source->child_status = -1; - } + child_watch_source->child_status = -1; + } else - child_watch_source->child_status = child_status; + child_watch_source->child_status = child_status; } +#else /* G_OS_WIN32 */ +#ifdef HAVE_PIDFD + if (child_watch_source->using_pidfd) + { + child_exited = child_watch_source->poll.revents & G_IO_IN; + + if (child_exited) + { + siginfo_t child_info = { 0, }; + + /* Get the exit status */ + if (waitid (P_PIDFD, child_watch_source->poll.fd, &child_info, WEXITED | WNOHANG) >= 0 && + child_info.si_pid != 0) + { + /* waitid() helpfully provides the wait status in a decomposed + * form which is quite useful. Unfortunately we have to report it + * to the #GChildWatchFunc as a waitpid()-style platform-specific + * wait status, so that the user code in #GChildWatchFunc can then + * call WIFEXITED() (etc.) on it. That means re-composing the + * status information. */ + child_watch_source->child_status = siginfo_t_to_wait_status (&child_info); + child_watch_source->child_exited = TRUE; + } + } + + return child_exited; + } +#endif /* HAVE_PIDFD */ + child_exited = g_atomic_int_get (&child_watch_source->child_exited); +#endif /* G_OS_WIN32 */ return child_exited; } @@ -5527,9 +5595,24 @@ g_child_watch_check (GSource *source) static void g_child_watch_finalize (GSource *source) { +#ifndef G_OS_WIN32 + GChildWatchSource *child_watch_source = (GChildWatchSource *) source; + + if (child_watch_source->using_pidfd) + { + if (child_watch_source->poll.fd >= 0) + close (child_watch_source->poll.fd); + return; + } + + G_LOCK (unix_signal_lock); + unix_child_watches = g_slist_remove (unix_child_watches, source); + unref_unix_signal_handler_unlocked (SIGCHLD); + G_UNLOCK (unix_signal_lock); +#endif /* G_OS_WIN32 */ } -#else /* G_OS_WIN32 */ +#ifndef G_OS_WIN32 static void wake_source (GSource *source) @@ -5663,79 +5746,6 @@ dispatch_unix_signals (void) } static gboolean -g_child_watch_prepare (GSource *source, - gint *timeout) -{ - GChildWatchSource *child_watch_source; - - child_watch_source = (GChildWatchSource *) source; - - return g_atomic_int_get (&child_watch_source->child_exited); -} - -#ifdef HAVE_PIDFD -static int -siginfo_t_to_wait_status (const siginfo_t *info) -{ - /* Each of these returns is essentially the inverse of WIFEXITED(), - * WIFSIGNALED(), etc. */ - switch (info->si_code) - { - case CLD_EXITED: - return W_EXITCODE (info->si_status, 0); - case CLD_KILLED: - return W_EXITCODE (0, info->si_status); - case CLD_DUMPED: - return W_EXITCODE (0, info->si_status | WCOREFLAG); - case CLD_CONTINUED: - return __W_CONTINUED; - case CLD_STOPPED: - case CLD_TRAPPED: - default: - return W_STOPCODE (info->si_status); - } -} -#endif /* HAVE_PIDFD */ - -static gboolean -g_child_watch_check (GSource *source) -{ - GChildWatchSource *child_watch_source; - - child_watch_source = (GChildWatchSource *) source; - -#ifdef HAVE_PIDFD - if (child_watch_source->using_pidfd) - { - gboolean child_exited = child_watch_source->poll.revents & G_IO_IN; - - if (child_exited) - { - siginfo_t child_info = { 0, }; - - /* Get the exit status */ - if (waitid (P_PIDFD, child_watch_source->poll.fd, &child_info, WEXITED | WNOHANG) >= 0 && - child_info.si_pid != 0) - { - /* waitid() helpfully provides the wait status in a decomposed - * form which is quite useful. Unfortunately we have to report it - * to the #GChildWatchFunc as a waitpid()-style platform-specific - * wait status, so that the user code in #GChildWatchFunc can then - * call WIFEXITED() (etc.) on it. That means re-composing the - * status information. */ - child_watch_source->child_status = siginfo_t_to_wait_status (&child_info); - child_watch_source->child_exited = TRUE; - } - } - - return child_exited; - } -#endif /* HAVE_PIDFD */ - - return g_atomic_int_get (&child_watch_source->child_exited); -} - -static gboolean g_unix_signal_watch_prepare (GSource *source, gint *timeout) { @@ -5913,24 +5923,6 @@ g_unix_signal_watch_finalize (GSource *source) G_UNLOCK (unix_signal_lock); } -static void -g_child_watch_finalize (GSource *source) -{ - GChildWatchSource *child_watch_source = (GChildWatchSource *) source; - - if (child_watch_source->using_pidfd) - { - if (child_watch_source->poll.fd >= 0) - close (child_watch_source->poll.fd); - return; - } - - G_LOCK (unix_signal_lock); - unix_child_watches = g_slist_remove (unix_child_watches, source); - unref_unix_signal_handler_unlocked (SIGCHLD); - G_UNLOCK (unix_signal_lock); -} - #endif /* G_OS_WIN32 */ static gboolean |