From 9988dc344d7f49282580fd41e1d2a3c30568d056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Fri, 5 Aug 2022 16:05:32 +0200 Subject: [PATCH] tests/test-client: Wait for processs to exit before shutting down This makes sure the client has exited cleanly before the Wayland server is teared down, causing the client to potentially end up with a broken pipe. Part-of: --- src/tests/meta-test-utils.c | 73 +++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/src/tests/meta-test-utils.c b/src/tests/meta-test-utils.c index 626317b46..a4980ef93 100644 --- a/src/tests/meta-test-utils.c +++ b/src/tests/meta-test-utils.c @@ -62,6 +62,11 @@ struct _MetaAsyncWaiter int counter_wait_value; }; +typedef struct +{ + GList *subprocesses; +} ClientProcessHandler; + G_DEFINE_QUARK (meta-test-client-error-quark, meta_test_client_error) static char *test_client_path; @@ -478,6 +483,66 @@ spawn_xwayland (gpointer user_data) return NULL; } +static void +on_prepare_shutdown (MetaBackend *backend, + ClientProcessHandler *process_handler) +{ + g_debug ("Waiting for test clients to exit before shutting down"); + while (process_handler->subprocesses) + g_main_context_iteration (NULL, TRUE); +} + +static void +wait_check_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + GSubprocess *subprocess = G_SUBPROCESS (source_object); + ClientProcessHandler *process_handler = user_data; + g_autoptr (GError) error = NULL; + + if (!g_subprocess_wait_check_finish (subprocess, result, &error)) + { + if (g_error_matches (error, G_SPAWN_EXIT_ERROR, 1)) + { + g_debug ("Test client process %s exited with exit status 1", + g_subprocess_get_identifier (subprocess)); + } + else + { + g_warning ("Test client process %s crashed with status %d", + g_subprocess_get_identifier (subprocess), + error->code); + } + } + + process_handler->subprocesses = g_list_remove (process_handler->subprocesses, + subprocess); +} + +static ClientProcessHandler * +ensure_process_handler (MetaContext *context) +{ + ClientProcessHandler *process_handler; + const char data_key[] = "test-client-subprocess-handler"; + MetaBackend *backend; + + process_handler = g_object_get_data (G_OBJECT (context), data_key); + if (process_handler) + return process_handler; + + process_handler = g_new0 (ClientProcessHandler, 1); + g_object_set_data_full (G_OBJECT (context), data_key, + process_handler, g_free); + + backend = meta_context_get_backend (context); + g_signal_connect (backend, "prepare-shutdown", + G_CALLBACK (on_prepare_shutdown), + process_handler); + + return process_handler; +} + MetaTestClient * meta_test_client_new (MetaContext *context, const char *id, @@ -487,6 +552,7 @@ meta_test_client_new (MetaContext *context, MetaTestClient *client; GSubprocessLauncher *launcher; GSubprocess *subprocess; + ClientProcessHandler *process_handler; MetaWaylandCompositor *compositor; const char *wayland_display_name; const char *x11_display_name; @@ -526,6 +592,13 @@ meta_test_client_new (MetaContext *context, if (!subprocess) return NULL; + process_handler = ensure_process_handler (context); + process_handler->subprocesses = g_list_prepend (process_handler->subprocesses, + subprocess); + g_subprocess_wait_check_async (subprocess, NULL, + wait_check_cb, + process_handler); + client = g_new0 (MetaTestClient, 1); client->type = type; client->id = g_strdup (id);