[glib: 4/6] gmain: Guarantee handler dispatch after receiving UNIX signal
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib: 4/6] gmain: Guarantee handler dispatch after receiving UNIX signal
- Date: Tue, 13 Nov 2018 16:04:48 +0000 (UTC)
commit 969b0e00b36d2ca4dddd2105d24574e56d2ea1ea
Author: Tomasz Miąsko <tomasz miasko gmail com>
Date: Fri Nov 2 00:00:00 2018 +0000
gmain: Guarantee handler dispatch after receiving UNIX signal
Guarantee that user signal callback is dispatched _after_ receiving a
signal as long as the handler expresses continued interest in receiving
such a notification.
Previously if a signal has been received during user callback dispatch
but before pending flag had been cleared then the signal would be
irrevocably lost.
This is a very useful guarantee to have in cases where signals are used
to signify a need for synchronization with external resources. For
example: reloading configuration file after SIGUSR1 or retrieving a
terminal size after SIGWINCH.
glib/gmain.c | 4 ++--
glib/tests/unix.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 53 insertions(+), 2 deletions(-)
---
diff --git a/glib/gmain.c b/glib/gmain.c
index 07ec867bc..85d0f2e43 100644
--- a/glib/gmain.c
+++ b/glib/gmain.c
@@ -5214,10 +5214,10 @@ g_unix_signal_watch_dispatch (GSource *source,
return FALSE;
}
- again = (callback) (user_data);
-
g_atomic_int_set (&unix_signal_source->pending, FALSE);
+ again = (callback) (user_data);
+
return again;
}
diff --git a/glib/tests/unix.c b/glib/tests/unix.c
index 9d55a6c58..82ffd0f56 100644
--- a/glib/tests/unix.c
+++ b/glib/tests/unix.c
@@ -245,6 +245,56 @@ test_sighup_nested (void)
g_main_loop_unref (mainloop);
}
+static gboolean
+on_sigwinch_received (gpointer data)
+{
+ GMainLoop *loop = (GMainLoop *) data;
+
+ sig_counter ++;
+
+ if (sig_counter == 1)
+ kill (getpid (), SIGWINCH);
+ else if (sig_counter == 2)
+ g_main_loop_quit (loop);
+ else if (sig_counter > 2)
+ g_assert_not_reached ();
+
+ /* Increase the time window in which an issue could happen. */
+ g_usleep (G_USEC_PER_SEC);
+
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+test_callback_after_signal (void)
+{
+ /* Checks that user signal callback is invoked *after* receiving a signal.
+ * In other words a new signal is never merged with the one being currently
+ * dispatched or whose dispatch had already finished. */
+
+ GMainLoop *mainloop;
+ GMainContext *context;
+ GSource *source;
+
+ sig_counter = 0;
+
+ context = g_main_context_new ();
+ mainloop = g_main_loop_new (context, FALSE);
+
+ source = g_unix_signal_source_new (SIGWINCH);
+ g_source_set_callback (source, on_sigwinch_received, mainloop, NULL);
+ g_source_attach (source, context);
+ g_source_unref (source);
+
+ g_assert_cmpint (sig_counter, ==, 0);
+ kill (getpid (), SIGWINCH);
+ g_main_loop_run (mainloop);
+ g_assert_cmpint (sig_counter, ==, 2);
+
+ g_main_loop_unref (mainloop);
+ g_main_context_unref (context);
+}
+
int
main (int argc,
char *argv[])
@@ -259,6 +309,7 @@ main (int argc,
g_test_add_func ("/glib-unix/sighup_again", test_sighup);
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);
return g_test_run();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]