Merge branch 'sa-onstack-unix-signals' into 'main'

gmain: Use alternate signal stack if the application provides one

See merge request GNOME/glib!3983
This commit is contained in:
Philip Withnall 2024-03-28 09:09:16 +00:00
commit ad903074a4
2 changed files with 59 additions and 0 deletions

View File

@ -5670,6 +5670,9 @@ ref_unix_signal_handler_unlocked (int signum)
action.sa_flags = SA_RESTART | SA_NOCLDSTOP;
#else
action.sa_flags = SA_NOCLDSTOP;
#endif
#ifdef SA_ONSTACK
action.sa_flags |= SA_ONSTACK;
#endif
sigaction (signum, &action, NULL);
}

View File

@ -30,6 +30,7 @@
#include "glib-unix.h"
#include "gstdio.h"
#include <signal.h>
#include <string.h>
#include <pwd.h>
#include <unistd.h>
@ -507,6 +508,7 @@ on_sig_received_2 (gpointer data)
static void
test_signal (int signum)
{
struct sigaction action;
GMainLoop *mainloop;
int id;
@ -515,6 +517,17 @@ test_signal (int signum)
sig_received = FALSE;
sig_counter = 0;
g_unix_signal_add (signum, on_sig_received, mainloop);
g_assert_no_errno (sigaction (signum, NULL, &action));
g_assert_true (action.sa_flags & SA_NOCLDSTOP);
#ifdef SA_RESTART
g_assert_true (action.sa_flags & SA_RESTART);
#endif
#ifdef SA_ONSTACK
g_assert_true (action.sa_flags & SA_ONSTACK);
#endif
kill (getpid (), signum);
g_assert (!sig_received);
id = g_timeout_add (5000, on_sig_timeout, mainloop);
@ -554,6 +567,46 @@ test_sigterm (void)
test_signal (SIGTERM);
}
static void
test_signal_alternate_stack (int signal)
{
#ifndef SA_ONSTACK
g_test_skip ("alternate stack is not supported");
#else
guint8 stack_memory[MINSIGSTKSZ];
guint8 zero_mem[MINSIGSTKSZ];
stack_t stack = { .ss_sp = stack_memory, .ss_size = MINSIGSTKSZ };
stack_t old_stack = { 0 };
memset (stack_memory, 0, MINSIGSTKSZ);
memset (zero_mem, 0, MINSIGSTKSZ);
g_assert_cmpmem (stack_memory, MINSIGSTKSZ, zero_mem, MINSIGSTKSZ);
g_assert_no_errno (sigaltstack (&stack, &old_stack));
test_signal (signal);
/* Very stupid check to ensure that the alternate stack is used instead of
* the default one. This test would fail if SA_ONSTACK wouldn't be set.
*/
g_assert_cmpint (memcmp (stack_memory, zero_mem, MINSIGSTKSZ), !=, 0);
g_assert_no_errno (sigaltstack (&old_stack, NULL));
#endif
}
static void
test_sighup_alternate_stack (void)
{
test_signal_alternate_stack (SIGHUP);
}
static void
test_sigterm_alternate_stack (void)
{
test_signal_alternate_stack (SIGTERM);
}
static void
test_sighup_add_remove (void)
{
@ -807,6 +860,9 @@ main (int argc,
g_test_add_func ("/glib-unix/sighup", test_sighup);
g_test_add_func ("/glib-unix/sigterm", test_sigterm);
g_test_add_func ("/glib-unix/sighup_again", test_sighup);
g_test_add_func ("/glib-unix/sighup/alternate-stack", test_sighup_alternate_stack);
g_test_add_func ("/glib-unix/sigterm/alternate-stack", test_sigterm_alternate_stack);
g_test_add_func ("/glib-unix/sighup_again/alternate-stack", test_sighup_alternate_stack);
g_test_add_func ("/glib-unix/sighup_add_remove", test_sighup_add_remove);
g_test_add_func ("/glib-unix/sighup_nested", test_sighup_nested);
g_test_add_func ("/glib-unix/callback_after_signal", test_callback_after_signal);