summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2023-03-28 14:38:08 +0200
committerThomas Haller <thaller@redhat.com>2023-05-17 07:59:17 +0200
commit55849fb5acff75bc2336db876d8883818903a625 (patch)
tree4494feb927935b5c9f239e6a553380f784a1d7c0
parentbbb40218fbbc686ee624dbb75d732fbd737cc608 (diff)
downloadglib-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.c192
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