diff --git a/bin/system-info.c b/bin/system-info.c index a0fa957a2aaf65cf6cffef43fce314796f377d7b..e8fab9c45ceeddc025ce474c5eb35db58aee97c0 100644 --- a/bin/system-info.c +++ b/bin/system-info.c @@ -119,6 +119,7 @@ #include <errno.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <getopt.h> #include <glib.h> @@ -394,6 +395,24 @@ print_libraries_details (JsonBuilder *builder, json_builder_begin_array (builder); jsonify_library_issues (builder, srt_library_get_issues (l->data)); json_builder_end_array (builder); + + int exit_status = srt_library_get_exit_status (l->data); + if (exit_status != 0 && exit_status != -1) + { + json_builder_set_member_name (builder, "exit-status"); + json_builder_add_int_value (builder, exit_status); + } + + int terminating_signal = srt_library_get_terminating_signal (l->data); + if (terminating_signal != 0) + { + json_builder_set_member_name (builder, "terminating-signal"); + json_builder_add_int_value (builder, terminating_signal); + + json_builder_set_member_name (builder, "terminating-signal-name"); + json_builder_add_string_value (builder, strsignal (terminating_signal)); + } + } missing_symbols = srt_library_get_missing_symbols (l->data); @@ -464,6 +483,23 @@ print_graphics_details(JsonBuilder *builder, json_builder_begin_array (builder); jsonify_graphics_issues (builder, srt_graphics_get_issues (g->data)); json_builder_end_array (builder); + int exit_status = srt_graphics_get_exit_status (g->data); + if (exit_status != 0 && exit_status != -1) + { + json_builder_set_member_name (builder, "exit-status"); + json_builder_add_int_value (builder, exit_status); + } + + int terminating_signal = srt_graphics_get_terminating_signal (g->data); + if (terminating_signal != 0) + { + json_builder_set_member_name (builder, "terminating-signal"); + json_builder_add_int_value (builder, terminating_signal); + + json_builder_set_member_name (builder, "terminating-signal-name"); + json_builder_add_string_value (builder, strsignal (terminating_signal)); + } + } json_builder_end_object (builder); // End object for parameters g_free (parameters); diff --git a/steam-runtime-tools/graphics-internal.h b/steam-runtime-tools/graphics-internal.h index a4a5c67df1a599f5c4d09f4832dd12a4a2acf61b..88148a202af7576c1f86f29cbe0986cf8ef61a35 100644 --- a/steam-runtime-tools/graphics-internal.h +++ b/steam-runtime-tools/graphics-internal.h @@ -37,6 +37,8 @@ * @issues: Problems found when checking @multiarch_tuple with * the given @winsys and @renderer. * @messages: Any debug messages found when checking graphics. + * @exit_status: exit status of helper, or -1 if it did not exit normally + * @termination_signal: signal that terminated the helper, or 0 * * Inline convenience function to create a new SrtGraphics. * This is not part of the public API. @@ -50,7 +52,9 @@ static inline SrtGraphics *_srt_graphics_new (const char *multiarch_tuple, const gchar *renderer_string, const gchar *version_string, SrtGraphicsIssues issues, - const gchar *messages); + const gchar *messages, + int exit_status, + int termination_signal); /* * _srt_graphics_hash_key: @@ -82,7 +86,9 @@ _srt_graphics_new (const char *multiarch_tuple, const gchar *renderer_string, const gchar *version_string, SrtGraphicsIssues issues, - const gchar *messages) + const gchar *messages, + int exit_status, + int terminating_signal) { g_return_val_if_fail (multiarch_tuple != NULL, NULL); return g_object_new (SRT_TYPE_GRAPHICS, @@ -94,6 +100,8 @@ _srt_graphics_new (const char *multiarch_tuple, "renderer-string", renderer_string, "version-string", version_string, "messages", messages, + "exit-status", exit_status, + "terminating-signal", terminating_signal, NULL); } diff --git a/steam-runtime-tools/graphics.c b/steam-runtime-tools/graphics.c index 85f7f10311bb335a71793a4ed3ab69f5784b6516..728335c6d47b7b2ae2ee20e2f820fd2205b97f86 100644 --- a/steam-runtime-tools/graphics.c +++ b/steam-runtime-tools/graphics.c @@ -34,7 +34,6 @@ #include <stdint.h> #include <string.h> -#include <sys/wait.h> #include <json-glib/json-glib.h> @@ -75,6 +74,8 @@ struct _SrtGraphics gchar *messages; gchar *renderer_string; gchar *version_string; + int exit_status; + int terminating_signal; }; struct _SrtGraphicsClass @@ -93,6 +94,8 @@ enum { PROP_RENDERING_INTERFACE, PROP_RENDERER_STRING, PROP_VERSION_STRING, + PROP_EXIT_STATUS, + PROP_TERMINATING_SIGNAL, N_PROPERTIES }; @@ -145,6 +148,14 @@ srt_graphics_get_property (GObject *object, g_value_set_string (value, self->version_string); break; + case PROP_EXIT_STATUS: + g_value_set_int (value, self->exit_status); + break; + + case PROP_TERMINATING_SIGNAL: + g_value_set_int (value, self->terminating_signal); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -218,6 +229,14 @@ srt_graphics_set_property (GObject *object, self->version_string = g_value_dup_string (value); break; + case PROP_EXIT_STATUS: + self->exit_status = g_value_get_int (value); + break; + + case PROP_TERMINATING_SIGNAL: + self->terminating_signal = g_value_get_int (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -298,6 +317,22 @@ srt_graphics_class_init (SrtGraphicsClass *cls) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + properties[PROP_EXIT_STATUS] = + g_param_spec_int ("exit-status", "Exit status", "Exit status of helper(s) executed. 0 on success, positive on unsuccessful exit(), -1 if killed by a signal or not run at all", + -1, + G_MAXINT, + 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + properties[PROP_TERMINATING_SIGNAL] = + g_param_spec_int ("terminating-signal", "Terminating signal", "Signal used to terminate helper process if any, 0 otherwise", + 0, + G_MAXINT, + 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, N_PROPERTIES, properties); } @@ -696,7 +731,9 @@ _srt_check_graphics (const char *helpers_path, gchar *output = NULL; gchar *child_stderr = NULL; gchar *child_stderr2 = NULL; + int wait_status = -1; int exit_status = -1; + int terminating_signal = 0; JsonParser *parser = NULL; const gchar *version_string = NULL; gchar *new_version_string = NULL; @@ -747,28 +784,29 @@ _srt_check_graphics (const char *helpers_path, NULL, /* user data */ &output, /* stdout */ &child_stderr, - &exit_status, + &wait_status, &error)) { g_debug ("An error occurred calling the helper: %s", error->message); issues |= SRT_GRAPHICS_ISSUES_CANNOT_LOAD; - goto out; } - if (exit_status != 0) + if (wait_status != 0) { - g_debug ("... wait status %d", exit_status); + g_debug ("... wait status %d", wait_status); issues |= SRT_GRAPHICS_ISSUES_CANNOT_LOAD; - // TERM signal gives us 124 from timeout man page - if (WIFEXITED (exit_status) && WEXITSTATUS (exit_status) == 124) // timeout command killed the helper + if (_srt_process_timeout_wait_status (wait_status, &exit_status, &terminating_signal)) { - g_debug ("helper killed by timeout command"); issues |= SRT_GRAPHICS_ISSUES_TIMEOUT; } goto out; } + else + { + exit_status = 0; + } /* We can't use `json_from_string()` directly because we are targeting an * older json-glib version */ @@ -815,26 +853,27 @@ _srt_check_graphics (const char *helpers_path, NULL, /* user data */ &output, /* stdout */ &child_stderr2, - &exit_status, + &wait_status, &error)) { g_debug ("An error occurred calling the helper: %s", error->message); issues |= SRT_GRAPHICS_ISSUES_CANNOT_DRAW; - goto out; } - if (exit_status != 0) + if (wait_status != 0) { - g_debug ("... wait status %d", exit_status); + g_debug ("... wait status %d", wait_status); issues |= SRT_GRAPHICS_ISSUES_CANNOT_DRAW; - // TERM signal gives us 124 from timeout man page - if (WIFEXITED (exit_status) && WEXITSTATUS (exit_status) == 124) // timeout command killed the helper + if (_srt_process_timeout_wait_status (wait_status, &exit_status, &terminating_signal)) { - g_debug ("helper killed by timeout command"); issues |= SRT_GRAPHICS_ISSUES_TIMEOUT; } } + else + { + exit_status = 0; + } } } else @@ -871,25 +910,27 @@ _srt_check_graphics (const char *helpers_path, NULL, /* user data */ &output, /* stdout */ &child_stderr2, - &exit_status, + &wait_status, &error)) { g_debug ("An error occurred calling the helper: %s", error->message); issues |= SRT_GRAPHICS_ISSUES_CANNOT_DRAW; - goto out; } - if (exit_status != 0) + if (wait_status != 0) { - g_debug ("... wait status %d", exit_status); + g_debug ("... wait status %d", wait_status); issues |= SRT_GRAPHICS_ISSUES_CANNOT_DRAW; - // TERM signal gives us 124 from timeout man page - if (WIFEXITED (exit_status) && WEXITSTATUS (exit_status) == 124) // timeout command killed the helper + if (_srt_process_timeout_wait_status (wait_status, &exit_status, &terminating_signal)) { - g_debug ("helper killed by timeout command"); issues |= SRT_GRAPHICS_ISSUES_TIMEOUT; } + + } + else + { + exit_status = 0; } } @@ -912,7 +953,9 @@ out: renderer_string, version_string, issues, - child_stderr); + child_stderr, + exit_status, + terminating_signal); if (parser != NULL) g_object_unref (parser); @@ -1033,6 +1076,37 @@ srt_graphics_get_version_string (SrtGraphics *self) return self->version_string; } +/** + * srt_graphics_get_exit_status: + * @self: a graphics object + * + * Return the exit status of helpers when testing the given graphics. + * + * Returns: 0 on success, positive on unsuccessful `exit()`, + * -1 if killed by a signal or not run at all + */ +int srt_graphics_get_exit_status (SrtGraphics *self) +{ + g_return_val_if_fail (SRT_IS_GRAPHICS (self), -1); + + return self->exit_status; +} + +/** + * srt_graphics_get_terminating_signal: + * @self: a graphics object + * + * Return the terminating signal used to terminate the helper if any. + * + * Returns: a signal number such as `SIGTERM`, or 0 if not killed by a signal or not run at all. + */ +int srt_graphics_get_terminating_signal (SrtGraphics *self) +{ + g_return_val_if_fail (SRT_IS_GRAPHICS (self), -1); + + return self->terminating_signal; +} + /** * srt_graphics_get_renderer_string: * @self: a graphics object diff --git a/steam-runtime-tools/graphics.h b/steam-runtime-tools/graphics.h index 8465a9987e90cc40aebf79a55ff478aa87a6c8aa..cc6b79f5c4291619ff20a07c25c04c9cc4efaa50 100644 --- a/steam-runtime-tools/graphics.h +++ b/steam-runtime-tools/graphics.h @@ -130,6 +130,8 @@ const char *srt_graphics_get_version_string (SrtGraphics *self); const char *srt_graphics_get_renderer_string (SrtGraphics *self); const char *srt_graphics_get_messages (SrtGraphics *self); gchar *srt_graphics_dup_parameters_string (SrtGraphics *self); +int srt_graphics_get_exit_status (SrtGraphics *self); +int srt_graphics_get_terminating_signal (SrtGraphics *self); typedef struct _SrtEglIcd SrtEglIcd; typedef struct _SrtEglIcdClass SrtEglIcdClass; diff --git a/steam-runtime-tools/library-internal.h b/steam-runtime-tools/library-internal.h index ebc11dea8fd812784808a680b703711a3ad62762..1463eb245d368e5edbe5c7c352e8ad2696926e26 100644 --- a/steam-runtime-tools/library-internal.h +++ b/steam-runtime-tools/library-internal.h @@ -43,6 +43,8 @@ * version * @dependencies: (nullable) (array zero-terminated=1) (element-type utf8): * Dependencies of @soname + * @exit_status: exit status of helper, or -1 if it did not exit normally + * @terminating_signal: signal that terminated the helper, or 0 * * Inline convenience function to create a new SrtLibrary. * This is not part of the public API. @@ -56,7 +58,9 @@ static inline SrtLibrary *_srt_library_new (const char *multiarch_tuple, const char *messages, const char * const *missing_symbols, const char * const *misversioned_symbols, - const char * const *dependencies); + const char * const *dependencies, + int exit_status, + int terminating_signal); #ifndef __GTK_DOC_IGNORE__ static inline SrtLibrary * @@ -67,7 +71,9 @@ _srt_library_new (const char *multiarch_tuple, const char *messages, const char * const *missing_symbols, const char * const *misversioned_symbols, - const char * const *dependencies) + const char * const *dependencies, + int exit_status, + int terminating_signal) { g_return_val_if_fail (multiarch_tuple != NULL, NULL); g_return_val_if_fail (soname != NULL, NULL); @@ -80,6 +86,8 @@ _srt_library_new (const char *multiarch_tuple, "multiarch-tuple", multiarch_tuple, "soname", soname, "misversioned-symbols", misversioned_symbols, + "exit-status", exit_status, + "terminating-signal", terminating_signal, NULL); } #endif diff --git a/steam-runtime-tools/library.c b/steam-runtime-tools/library.c index 681d4bb98980d5d035d12aa7dfc6f69cf564ebf1..b677124362ffdeab492d690fb198c7e1d0f1d941 100644 --- a/steam-runtime-tools/library.c +++ b/steam-runtime-tools/library.c @@ -57,6 +57,8 @@ struct _SrtLibrary GStrv misversioned_symbols; GQuark multiarch_tuple; SrtLibraryIssues issues; + int exit_status; + int terminating_signal; }; struct _SrtLibraryClass @@ -75,6 +77,8 @@ enum { PROP_MULTIARCH_TUPLE, PROP_SONAME, PROP_MISVERSIONED_SYMBOLS, + PROP_EXIT_STATUS, + PROP_TERMINATING_SIGNAL, N_PROPERTIES }; @@ -127,6 +131,14 @@ srt_library_get_property (GObject *object, g_value_set_boxed (value, self->misversioned_symbols); break; + case PROP_EXIT_STATUS: + g_value_set_int (value, self->exit_status); + break; + + case PROP_TERMINATING_SIGNAL: + g_value_set_int (value, self->terminating_signal); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -213,6 +225,14 @@ srt_library_set_property (GObject *object, break; + case PROP_EXIT_STATUS: + self->exit_status = g_value_get_int (value); + break; + + case PROP_TERMINATING_SIGNAL: + self->terminating_signal = g_value_get_int (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -297,6 +317,22 @@ srt_library_class_init (SrtLibraryClass *cls) G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + properties[PROP_EXIT_STATUS] = + g_param_spec_int ("exit-status", "Exit status", "Exit status of helper(s) executed. 0 on success, positive on unsuccessful exit(), -1 if killed by a signal or not run at all", + -1, + G_MAXINT, + 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + properties[PROP_TERMINATING_SIGNAL] = + g_param_spec_int ("terminating-signal", "Terminating signal", "Signal used to terminate helper process if any, 0 otherwise", + 0, + G_MAXINT, + 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, N_PROPERTIES, properties); } @@ -399,6 +435,37 @@ srt_library_get_dependencies (SrtLibrary *self) return (const char * const *) self->dependencies; } +/** + * srt_library_get_exit_status: + * @self: a library + * + * Return the exit status of helpers when testing the given library. + * + * Returns: 0 on success, positive on unsuccessful `exit()`, or + * -1 if killed by a signal or not run at all + */ +int srt_library_get_exit_status (SrtLibrary *self) +{ + g_return_val_if_fail (SRT_IS_LIBRARY (self), -1); + + return self->exit_status; +} + +/** + * srt_library_get_terminating_signal: + * @self: a library + * + * Return the terminating signal used to terminate the helper if any. + * + * Returns: a signal number such as `SIGTERM`, or 0 if not killed by a signal or not run at all. + */ +int srt_library_get_terminating_signal (SrtLibrary *self) +{ + g_return_val_if_fail (SRT_IS_LIBRARY (self), -1); + + return self->terminating_signal; +} + /** * srt_library_get_missing_symbols: * @self: a library @@ -492,7 +559,9 @@ _srt_check_library_presence (const char *helpers_path, gchar *output = NULL; gchar *child_stderr = NULL; gchar *absolute_path = NULL; + int wait_status = -1; int exit_status = -1; + int terminating_signal = 0; JsonParser *parser = NULL; JsonNode *node = NULL; JsonObject *json; @@ -507,6 +576,8 @@ _srt_check_library_presence (const char *helpers_path, GStrv my_environ = NULL; const gchar *ld_preload; gchar *filtered_preload = NULL; + SrtHelperFlags flags = SRT_HELPER_FLAGS_TIME_OUT; + GString *log_args = NULL; g_return_val_if_fail (soname != NULL, SRT_LIBRARY_ISSUES_INTERNAL_ERROR); g_return_val_if_fail (multiarch != NULL, SRT_LIBRARY_ISSUES_INTERNAL_ERROR); @@ -518,7 +589,7 @@ _srt_check_library_presence (const char *helpers_path, issues |= SRT_LIBRARY_ISSUES_UNKNOWN_EXPECTATIONS; argv = _srt_get_helper (helpers_path, multiarch, "inspect-library", - SRT_HELPER_FLAGS_NONE, &error); + flags, &error); if (argv == NULL) { @@ -529,7 +600,19 @@ _srt_check_library_presence (const char *helpers_path, goto out; } - g_debug ("Checking library %s integrity with %s", soname, (gchar *)g_ptr_array_index (argv, 0)); + log_args = g_string_new (""); + + for (guint i = 0; i < argv->len; ++i) + { + if (i > 0) + { + g_string_append_c (log_args, ' '); + } + g_string_append (log_args, g_ptr_array_index (argv, i)); + } + + g_debug ("Checking library %s integrity with %s ", soname, log_args->str); + g_string_free (log_args, TRUE); switch (symbols_format) { @@ -568,25 +651,33 @@ _srt_check_library_presence (const char *helpers_path, if (!g_spawn_sync (NULL, /* working directory */ (gchar **) argv->pdata, my_environ, /* envp */ - 0, /* flags */ + G_SPAWN_SEARCH_PATH, /* flags */ NULL, /* child setup */ NULL, /* user data */ &output, /* stdout */ &child_stderr, - &exit_status, + &wait_status, &error)) { g_debug ("An error occurred calling the helper: %s", error->message); issues |= SRT_LIBRARY_ISSUES_CANNOT_LOAD; - goto out; } - if (exit_status != 0) + if (wait_status != 0) { - g_debug ("... wait status %d", exit_status); + g_debug ("... wait status %d", wait_status); issues |= SRT_LIBRARY_ISSUES_CANNOT_LOAD; + + if (_srt_process_timeout_wait_status (wait_status, &exit_status, &terminating_signal)) + { + issues |= SRT_LIBRARY_ISSUES_TIMEOUT; + } goto out; } + else + { + exit_status = 0; + } /* We can't use `json_from_string()` directly because we are targeting an * older json-glib version */ @@ -664,7 +755,9 @@ out: child_stderr, (const char **) missing_symbols, (const char **) misversioned_symbols, - (const char **) dependencies); + (const char **) dependencies, + exit_status, + terminating_signal); if (parser != NULL) g_object_unref (parser); diff --git a/steam-runtime-tools/library.h b/steam-runtime-tools/library.h index 9f4fff0dd3d1e7387b51e2e9495eeb3cfbd5a6c4..011f9c16ce9503545415fcdd2ea54f10775dc385 100644 --- a/steam-runtime-tools/library.h +++ b/steam-runtime-tools/library.h @@ -57,6 +57,7 @@ GType srt_library_get_type (void); * @SRT_LIBRARY_ISSUES_UNKNOWN_EXPECTATIONS: No directory containing * expected ABIs has been set, so we cannot know which libraries we are * meant to have found + * @SRT_LIBRARY_ISSUES_TIMEOUT: Helper timed out when executing * * A bitfield with flags representing problems with a library, or * %SRT_LIBRARY_ISSUES_NONE (which is numerically zero) if no problems @@ -71,6 +72,7 @@ typedef enum SRT_LIBRARY_ISSUES_MISVERSIONED_SYMBOLS = (1 << 2), SRT_LIBRARY_ISSUES_INTERNAL_ERROR = (1 << 3), SRT_LIBRARY_ISSUES_UNKNOWN_EXPECTATIONS = (1 << 4), + SRT_LIBRARY_ISSUES_TIMEOUT = (1 << 5), SRT_LIBRARY_ISSUES_NONE = 0 } SrtLibraryIssues; @@ -100,6 +102,8 @@ SrtLibraryIssues srt_check_library_presence (const char *soname, const char *symbols_path, SrtLibrarySymbolsFormat symbols_format, SrtLibrary **more_details_out); +int srt_library_get_exit_status (SrtLibrary *self); +int srt_library_get_terminating_signal (SrtLibrary *self); #ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtLibrary, g_object_unref) diff --git a/steam-runtime-tools/utils-internal.h b/steam-runtime-tools/utils-internal.h index dc74724aec8959a6aaf8fedc5edab45647eb4089..396a76acb7679b63099a41758a4e94ea7afed8bc 100644 --- a/steam-runtime-tools/utils-internal.h +++ b/steam-runtime-tools/utils-internal.h @@ -44,3 +44,7 @@ G_GNUC_INTERNAL GPtrArray *_srt_get_helper (const char *helpers_path, gchar *_srt_filter_gameoverlayrenderer (const gchar *input); G_GNUC_INTERNAL const char *_srt_find_myself (const char **helpers_path_out, GError **error); + +G_GNUC_INTERNAL gboolean _srt_process_timeout_wait_status (int wait_status, + int *exit_status, + int *terminating_signal); diff --git a/steam-runtime-tools/utils.c b/steam-runtime-tools/utils.c index 1c2b95bcd2370906b3f8a3669469e158fa7bb255..d324b5db26576b4c61ce57d29f7e7eafe63484cd 100644 --- a/steam-runtime-tools/utils.c +++ b/steam-runtime-tools/utils.c @@ -32,6 +32,7 @@ #include <link.h> #include <stdio.h> #include <string.h> +#include <sys/wait.h> #include <unistd.h> #ifdef HAVE_SYS_AUXV_H @@ -151,6 +152,57 @@ _srt_check_not_setuid (void) #define RELOCATABLE_PKGLIBDIR \ MULTIARCH_LIBDIR "/steam-runtime-tools-" _SRT_API_MAJOR +/** + * _srt_process_timeout_wait_status: + * + * @wait_status: The wait_status from g_spawn_sync to process + * @exit_status: (not optional): The exit_status to populate + * @terminating_signal: (not optional): The terminating signal if any, 0 otherwise + * + * Check given wait_status and populate given exit_status and terminating_signal + * + * Returns: True if timeout, false otherwise + */ +G_GNUC_INTERNAL gboolean +_srt_process_timeout_wait_status (int wait_status, int *exit_status, int *terminating_signal) +{ + gboolean timed_out = FALSE; + + g_return_val_if_fail (exit_status != NULL, FALSE); + g_return_val_if_fail (terminating_signal != NULL, FALSE); + + *exit_status = -1; + *terminating_signal = 0; + + if (WIFEXITED (wait_status)) + { + *exit_status = WEXITSTATUS (wait_status); + + if (*exit_status > 128) + { + g_debug ("-> killed by signal %d", (*exit_status - 128)); + *terminating_signal = (*exit_status - 128); + } + else if (*exit_status == 124) + { + g_debug ("-> timed out"); + timed_out = TRUE; + } + } + else if (WIFSIGNALED (wait_status)) + { + g_debug ("-> timeout killed by signal %d", WTERMSIG (wait_status)); + *terminating_signal = WTERMSIG (wait_status); + } + else + { + g_critical ("Somehow got a wait_status that was neither exited nor signaled"); + g_return_val_if_reached (FALSE); + } + + return timed_out; +} + G_GNUC_INTERNAL const char * _srt_find_myself (const char **helpers_path_out, GError **error) diff --git a/tests/graphics.c b/tests/graphics.c index 2fac6cc0300d23a21aa3c022b80a0e85da397f29..d0d489704823f8c356eaf24866b26b3f49fcfe5e 100644 --- a/tests/graphics.c +++ b/tests/graphics.c @@ -200,6 +200,8 @@ test_object (Fixture *f, gchar *tuple; gchar *renderer; gchar *version; + int exit_status; + int terminating_signal; graphics = _srt_graphics_new("mock-good", SRT_WINDOW_SYSTEM_GLX, @@ -208,7 +210,9 @@ test_object (Fixture *f, SRT_TEST_GOOD_GRAPHICS_RENDERER, SRT_TEST_GOOD_GRAPHICS_VERSION, SRT_GRAPHICS_ISSUES_NONE, - ""); + "", + 0, + 0); g_assert_cmpint (srt_graphics_get_issues (graphics), ==, SRT_GRAPHICS_ISSUES_NONE); g_assert_cmpstr (srt_graphics_get_multiarch_tuple (graphics), ==, @@ -220,6 +224,8 @@ test_object (Fixture *f, g_assert_cmpstr (srt_graphics_get_messages (graphics), ==, NULL); vendor_neutral = srt_graphics_library_is_vendor_neutral (graphics, &library_vendor); g_assert_cmpint (library_vendor, ==, SRT_GRAPHICS_LIBRARY_VENDOR_GLVND); + g_assert_cmpint (srt_graphics_get_exit_status (graphics), ==, 0); + g_assert_cmpint (srt_graphics_get_terminating_signal (graphics), ==, 0); g_assert_true (vendor_neutral); g_object_get (graphics, "messages", &messages, @@ -228,6 +234,8 @@ test_object (Fixture *f, "library-vendor", &library_vendor, "renderer-string", &renderer, "version-string", &version, + "exit-status", &exit_status, + "terminating-signal", &terminating_signal, NULL); g_assert_cmpint (issues, ==, SRT_GRAPHICS_ISSUES_NONE); g_assert_cmpint (library_vendor, ==, SRT_GRAPHICS_LIBRARY_VENDOR_GLVND); @@ -235,6 +243,8 @@ test_object (Fixture *f, g_assert_cmpstr (tuple, ==, "mock-good"); g_assert_cmpstr (renderer, ==, SRT_TEST_GOOD_GRAPHICS_RENDERER); g_assert_cmpstr (version, ==, SRT_TEST_GOOD_GRAPHICS_VERSION); + g_assert_cmpint (exit_status, ==, 0); + g_assert_cmpint (terminating_signal, ==, 0); g_free (messages); g_free (tuple); g_free (renderer); @@ -254,6 +264,8 @@ test_good_graphics (Fixture *f, gchar *tuple; gchar *renderer; gchar *version; + int exit_status; + int terminating_signal; SrtSystemInfo *info = srt_system_info_new (NULL); srt_system_info_set_helpers_path (info, f->builddir); @@ -268,16 +280,22 @@ test_good_graphics (Fixture *f, SRT_TEST_GOOD_GRAPHICS_RENDERER); g_assert_cmpstr (srt_graphics_get_version_string (graphics), ==, SRT_TEST_GOOD_GRAPHICS_VERSION); + g_assert_cmpint (srt_graphics_get_exit_status (graphics), ==, 0); + g_assert_cmpint (srt_graphics_get_terminating_signal (graphics), ==, 0); g_object_get (graphics, "multiarch-tuple", &tuple, "issues", &issues, "renderer-string", &renderer, "version-string", &version, + "exit-status", &exit_status, + "terminating-signal", &terminating_signal, NULL); g_assert_cmpint (issues, ==, SRT_GRAPHICS_ISSUES_NONE); g_assert_cmpstr (tuple, ==, "mock-good"); g_assert_cmpstr (renderer, ==, SRT_TEST_GOOD_GRAPHICS_RENDERER); g_assert_cmpstr (version, ==, SRT_TEST_GOOD_GRAPHICS_VERSION); + g_assert_cmpint (exit_status, ==, 0); + g_assert_cmpint (terminating_signal, ==, 0); g_free (tuple); g_free (renderer); g_free (version); @@ -427,6 +445,8 @@ test_bad_graphics (Fixture *f, gchar *tuple; gchar *renderer; gchar *version; + int exit_status; + int terminating_signal; SrtSystemInfo *info = srt_system_info_new (NULL); srt_system_info_set_helpers_path (info, f->builddir); @@ -443,6 +463,9 @@ test_bad_graphics (Fixture *f, NULL); g_assert_cmpstr (srt_graphics_get_messages (graphics), ==, "Waffle error: 0x2 WAFFLE_ERROR_UNKNOWN: XOpenDisplay failed\n"); + g_assert_cmpint (srt_graphics_get_exit_status (graphics), ==, 1); + g_assert_cmpint (srt_graphics_get_terminating_signal (graphics), ==, 0); + /* We used "mock-bad" for the architecture so, when checking the library vendor, * we will not be able to call the helper `mock-bad-check-library`. * For this reason we expect %SRT_GRAPHICS_LIBRARY_VENDOR_UNKNOWN */ @@ -456,6 +479,8 @@ test_bad_graphics (Fixture *f, "library-vendor", &library_vendor, "renderer-string", &renderer, "version-string", &version, + "exit-status", &exit_status, + "terminating-signal", &terminating_signal, NULL); g_assert_cmpint (issues, ==, SRT_GRAPHICS_ISSUES_CANNOT_LOAD); g_assert_cmpint (library_vendor, ==, SRT_GRAPHICS_LIBRARY_VENDOR_UNKNOWN); @@ -464,6 +489,8 @@ test_bad_graphics (Fixture *f, g_assert_cmpstr (tuple, ==, "mock-bad"); g_assert_cmpstr (renderer, ==, NULL); g_assert_cmpstr (version, ==, NULL); + g_assert_cmpint (exit_status, ==, 1); + g_assert_cmpint (terminating_signal, ==, 0); g_free (messages); g_free (tuple); g_free (renderer); @@ -485,6 +512,8 @@ test_timeout_graphics (Fixture *f, gchar *tuple; gchar *renderer; gchar *version; + int exit_status; + int terminating_signal; SrtSystemInfo *info = srt_system_info_new (NULL); srt_system_info_set_helpers_path (info, f->builddir); @@ -502,17 +531,24 @@ test_timeout_graphics (Fixture *f, NULL); g_assert_cmpstr (srt_graphics_get_version_string (graphics), ==, NULL); + // Timeout has exit code 124 + g_assert_cmpint (srt_graphics_get_exit_status (graphics), ==, 124); + g_assert_cmpint (srt_graphics_get_terminating_signal (graphics), ==, 0); g_object_get (graphics, "multiarch-tuple", &tuple, "issues", &issues, "renderer-string", &renderer, "version-string", &version, + "exit-status", &exit_status, + "terminating-signal", &terminating_signal, NULL); g_assert_cmphex ((issues & SRT_GRAPHICS_ISSUES_CANNOT_LOAD), ==, SRT_GRAPHICS_ISSUES_CANNOT_LOAD); g_assert_cmphex ((issues & SRT_GRAPHICS_ISSUES_TIMEOUT), ==, SRT_GRAPHICS_ISSUES_TIMEOUT); g_assert_cmpstr (tuple, ==, "mock-hanging"); g_assert_cmpstr (renderer, ==, NULL); g_assert_cmpstr (version, ==, NULL); + g_assert_cmpint (exit_status, ==, 124); + g_assert_cmpint (terminating_signal, ==, 0); g_free (tuple); g_free (renderer); g_free (version); @@ -533,6 +569,8 @@ test_software_rendering (Fixture *f, gchar *tuple; gchar *renderer; gchar *version; + int exit_status; + int terminating_signal; SrtSystemInfo *info = srt_system_info_new (NULL); srt_system_info_set_helpers_path (info, f->builddir); @@ -547,16 +585,23 @@ test_software_rendering (Fixture *f, SRT_TEST_SOFTWARE_GRAPHICS_RENDERER); g_assert_cmpstr (srt_graphics_get_version_string (graphics), ==, SRT_TEST_SOFTWARE_GRAPHICS_VERSION); + g_assert_cmpint (srt_graphics_get_exit_status (graphics), ==, 0); + g_assert_cmpint (srt_graphics_get_terminating_signal (graphics), ==, 0); + g_object_get (graphics, "multiarch-tuple", &tuple, "issues", &issues, "renderer-string", &renderer, "version-string", &version, + "exit-status", &exit_status, + "terminating-signal", &terminating_signal, NULL); g_assert_cmpint (issues, ==, SRT_GRAPHICS_ISSUES_SOFTWARE_RENDERING); g_assert_cmpstr (tuple, ==, "mock-software"); g_assert_cmpstr (renderer, ==, SRT_TEST_SOFTWARE_GRAPHICS_RENDERER); g_assert_cmpstr (version, ==, SRT_TEST_SOFTWARE_GRAPHICS_VERSION); + g_assert_cmpint (exit_status, ==, 0); + g_assert_cmpint (terminating_signal, ==, 0); g_free (tuple); g_free (renderer); g_free (version); @@ -577,6 +622,8 @@ test_good_vulkan (Fixture *f, gchar *tuple; gchar *renderer; gchar *version; + int exit_status; + int terminating_signal; SrtSystemInfo *info = srt_system_info_new (NULL); srt_system_info_set_helpers_path (info, f->builddir); @@ -591,16 +638,23 @@ test_good_vulkan (Fixture *f, SRT_TEST_GOOD_GRAPHICS_RENDERER); g_assert_cmpstr (srt_graphics_get_version_string (graphics), ==, SRT_TEST_GOOD_VULKAN_VERSION); + g_assert_cmpint (srt_graphics_get_exit_status (graphics), ==, 0); + g_assert_cmpint (srt_graphics_get_terminating_signal (graphics), ==, 0); + g_object_get (graphics, "multiarch-tuple", &tuple, "issues", &issues, "renderer-string", &renderer, "version-string", &version, + "exit-status", &exit_status, + "terminating-signal", &terminating_signal, NULL); g_assert_cmpint (issues, ==, SRT_GRAPHICS_ISSUES_NONE); g_assert_cmpstr (tuple, ==, "mock-good"); g_assert_cmpstr (renderer, ==, SRT_TEST_GOOD_GRAPHICS_RENDERER); g_assert_cmpstr (version, ==, SRT_TEST_GOOD_VULKAN_VERSION); + g_assert_cmpint (exit_status, ==, 0); + g_assert_cmpint (terminating_signal, ==, 0); g_free (tuple); g_free (renderer); g_free (version); @@ -621,6 +675,8 @@ test_bad_vulkan (Fixture *f, gchar *tuple; gchar *renderer; gchar *version; + int exit_status; + int terminating_signal; SrtSystemInfo *info = srt_system_info_new (NULL); srt_system_info_set_helpers_path (info, f->builddir); @@ -635,16 +691,23 @@ test_bad_vulkan (Fixture *f, NULL); g_assert_cmpstr (srt_graphics_get_version_string (graphics), ==, NULL); + g_assert_cmpint (srt_graphics_get_exit_status (graphics), ==, 1); + g_assert_cmpint (srt_graphics_get_terminating_signal (graphics), ==, 0); + g_object_get (graphics, "multiarch-tuple", &tuple, "issues", &issues, "renderer-string", &renderer, "version-string", &version, + "exit-status", &exit_status, + "terminating-signal", &terminating_signal, NULL); g_assert_cmpint (issues, ==, SRT_GRAPHICS_ISSUES_CANNOT_LOAD); g_assert_cmpstr (tuple, ==, "mock-bad"); g_assert_cmpstr (renderer, ==, NULL); g_assert_cmpstr (version, ==, NULL); + g_assert_cmpint (exit_status, ==, 1); + g_assert_cmpint (terminating_signal, ==, 0); g_free (tuple); g_free (renderer); g_free (version); @@ -665,6 +728,8 @@ test_mixed_vulkan (Fixture *f, gchar *tuple; gchar *renderer; gchar *version; + int exit_status; + int terminating_signal; SrtSystemInfo *info = srt_system_info_new (NULL); srt_system_info_set_helpers_path (info, f->builddir); @@ -679,16 +744,24 @@ test_mixed_vulkan (Fixture *f, SRT_TEST_GOOD_GRAPHICS_RENDERER); g_assert_cmpstr (srt_graphics_get_version_string (graphics), ==, SRT_TEST_GOOD_VULKAN_VERSION); + g_assert_cmpint (srt_graphics_get_exit_status (graphics), ==, 1); + g_assert_cmpint (srt_graphics_get_terminating_signal (graphics), ==, 0); + g_object_get (graphics, "multiarch-tuple", &tuple, "issues", &issues, "renderer-string", &renderer, "version-string", &version, + "exit-status", &exit_status, + "terminating-signal", &terminating_signal, NULL); g_assert_cmpint (issues, ==, SRT_GRAPHICS_ISSUES_CANNOT_DRAW); g_assert_cmpstr (tuple, ==, "mock-mixed"); g_assert_cmpstr (renderer, ==, SRT_TEST_GOOD_GRAPHICS_RENDERER); g_assert_cmpstr (version, ==, SRT_TEST_GOOD_VULKAN_VERSION); + g_assert_cmpint (exit_status, ==, 1); + g_assert_cmpint (terminating_signal, ==, 0); + g_free (tuple); g_free (renderer); g_free (version); @@ -741,6 +814,49 @@ test_mixed_gl (Fixture *f, g_object_unref (info); } +/* + * Test a mock system with sigusr terminating signal + */ +static void +test_sigusr (Fixture *f, + gconstpointer context) +{ + SrtGraphics *graphics = NULL; + SrtGraphicsIssues issues; + gchar *tuple; + int exit_status; + int terminating_signal; + + SrtSystemInfo *info = srt_system_info_new (NULL); + srt_system_info_set_helpers_path (info, f->builddir); + + issues = srt_system_info_check_graphics (info, + "mock-sigusr", + SRT_WINDOW_SYSTEM_GLX, + SRT_RENDERING_INTERFACE_GL, + &graphics); + g_assert_cmpint (issues, ==, SRT_GRAPHICS_ISSUES_CANNOT_LOAD); + g_object_get (graphics, + "multiarch-tuple", &tuple, + "issues", &issues, + "exit-status", &exit_status, + "terminating-signal", &terminating_signal, + NULL); + g_assert_cmpint (issues, ==, SRT_GRAPHICS_ISSUES_CANNOT_LOAD); + g_assert_cmpstr (tuple, ==, "mock-sigusr"); + /* Depending on the version of timeout(1), it will have either + * exited with status 128 + SIGUSR1, or killed itself with SIGUSR1 */ + if (exit_status != -1) + { + g_assert_cmpint (exit_status, ==, 128 + SIGUSR1); + } + g_assert_cmpint (terminating_signal, ==, SIGUSR1); + g_free (tuple); + + g_object_unref (graphics); + g_object_unref (info); +} + /* * Assert that @icd is internally consistent. */ @@ -1581,6 +1697,8 @@ main (int argc, setup, test_normalize_window_system, teardown); g_test_add ("/graphics/gl-mixed", Fixture, NULL, setup, test_mixed_gl, teardown); + g_test_add ("/graphics/sigusr", Fixture, NULL, + setup, test_sigusr, teardown); g_test_add ("/graphics/vulkan", Fixture, NULL, setup, test_good_vulkan, teardown); diff --git a/tests/library.c b/tests/library.c index dc1b6d7a084974207b1ca56bff6b73ff6df9a03b..833e53c1e14a4faf12a20956b1c07ae14b6954e1 100644 --- a/tests/library.c +++ b/tests/library.c @@ -88,7 +88,9 @@ test_object (Fixture *f, "", NULL, NULL, - NULL); + NULL, + 0, + 0); g_assert_cmpint (srt_library_get_issues (library), ==, SRT_LIBRARY_ISSUES_NONE); g_assert_cmpstr (srt_library_get_messages (library), ==, NULL); @@ -145,7 +147,9 @@ test_object (Fixture *f, "ld.so: libjpeg.so.62: nope\n", one_missing, one_misversioned, - two_deps); + two_deps, + 0, + 0); g_assert_cmpint (srt_library_get_issues (library) & SRT_LIBRARY_ISSUES_MISSING_SYMBOLS, !=, 0); g_assert_cmpint (srt_library_get_issues (library) & @@ -338,6 +342,8 @@ test_deb_symbols (Fixture *f, SRT_LIBRARY_SYMBOLS_FORMAT_DEB_SYMBOLS, &library); g_assert_cmpint (issues, ==, SRT_LIBRARY_ISSUES_MISSING_SYMBOLS); + g_assert_cmpint (srt_library_get_exit_status (library), ==, 0); + g_assert_cmpint (srt_library_get_terminating_signal (library), ==, 0); /* If we had mistakenly parsed the sections that refer to libzextra.so.0 * and libzmore.so.0, then we would see more missing symbols than this. @@ -695,6 +701,8 @@ test_missing_library (Fixture *f, (SRT_LIBRARY_ISSUES_CANNOT_LOAD | SRT_LIBRARY_ISSUES_UNKNOWN_EXPECTATIONS)); g_assert_cmpstr (srt_library_get_absolute_path (library), ==, NULL); + g_assert_cmpint (srt_library_get_exit_status (library), ==, 1); + g_assert_cmpint (srt_library_get_terminating_signal (library), ==, 0); missing_symbols = srt_library_get_missing_symbols (library); g_assert_nonnull (missing_symbols); @@ -733,6 +741,8 @@ test_missing_arch (Fixture *f, (SRT_LIBRARY_ISSUES_CANNOT_LOAD | SRT_LIBRARY_ISSUES_UNKNOWN_EXPECTATIONS)); g_assert_cmpstr (srt_library_get_absolute_path (library), ==, NULL); + g_assert_cmpint (srt_library_get_exit_status (library), ==, -1); + g_assert_cmpint (srt_library_get_terminating_signal (library), ==, 0); missing_symbols = srt_library_get_missing_symbols (library); g_assert_nonnull (missing_symbols); diff --git a/tests/meson.build b/tests/meson.build index a74241ff0a3387fc8a9f01ee07bd545349ee1f80..55737f34f8418ecbc2fd95ff4da8b160fcfa51a4 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -260,4 +260,11 @@ executable( install_dir: tests_dir ) +executable( + 'mock-sigusr-wflinfo', + 'mock-sigusr-wflinfo.c', + install: true, + install_dir: tests_dir +) + # vim:set sw=2 sts=2 et: diff --git a/tests/mock-sigusr-wflinfo.c b/tests/mock-sigusr-wflinfo.c new file mode 100644 index 0000000000000000000000000000000000000000..a57158eeb88273f0db3aacff7b4e849ecb58f7a7 --- /dev/null +++ b/tests/mock-sigusr-wflinfo.c @@ -0,0 +1,36 @@ +/* + * Copyright © 2019 Collabora Ltd. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <signal.h> + +int +main (int argc, + char **argv) +{ + raise (SIGUSR1); + + return 0; +} +