From: Szymon Lukasz <[email protected]> Block SIGWINCH, so it is delivered only via signalfd. Install a handler that uses NotifierList to tell interested parties about SIGWINCH delivery.
Signed-off-by: Szymon Lukasz <[email protected]> [Filip: add sigwinch_remove_notifier, call it in curses_cleanup] Signed-off-by: Filip Hejsek <[email protected]> Reviewed-by: Marc-André Lureau <[email protected]> Message-ID: <[email protected]> --- include/qemu/main-loop.h | 5 +++++ ui/curses.c | 21 +++++++++++++++------ util/main-loop.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h index 8c1241a2c11c..533d4c2be413 100644 --- a/include/qemu/main-loop.h +++ b/include/qemu/main-loop.h @@ -449,4 +449,9 @@ typedef struct MainLoopPoll { void main_loop_poll_add_notifier(Notifier *notify); void main_loop_poll_remove_notifier(Notifier *notify); +#ifndef _WIN32 +void sigwinch_add_notifier(Notifier *n); +void sigwinch_remove_notifier(Notifier *n); +#endif + #endif diff --git a/ui/curses.c b/ui/curses.c index 4db32b6168d6..9079bfbee469 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -33,6 +33,7 @@ #include <iconv.h> #include "qapi/error.h" +#include "qemu/main-loop.h" #include "qemu/module.h" #include "ui/console.h" #include "ui/input.h" @@ -149,7 +150,7 @@ static void curses_resize(DisplayChangeListener *dcl, } #if !defined(_WIN32) && defined(SIGWINCH) && defined(KEY_RESIZE) -static volatile sig_atomic_t got_sigwinch; +static bool got_sigwinch; static void curses_winch_check(void) { struct winsize { @@ -172,21 +173,28 @@ static void curses_winch_check(void) invalidate = 1; } -static void curses_winch_handler(int signum) +static void curses_winch_handler(Notifier *n, void *data) { got_sigwinch = true; } +static Notifier winch_notifier = { + .notify = curses_winch_handler +}; + static void curses_winch_init(void) { - struct sigaction old, winch = { - .sa_handler = curses_winch_handler, - }; - sigaction(SIGWINCH, &winch, &old); + sigwinch_add_notifier(&winch_notifier); +} + +static void curses_winch_cleanup(void) +{ + sigwinch_remove_notifier(&winch_notifier); } #else static void curses_winch_check(void) {} static void curses_winch_init(void) {} +static void curses_winch_cleanup(void) {} #endif static void curses_cursor_position(DisplayChangeListener *dcl, @@ -417,6 +425,7 @@ static void curses_cleanup(void) return; } + curses_winch_cleanup(); endwin(); qemu_console_unregister_listener(dcl); g_clear_pointer(&dcl, g_free); diff --git a/util/main-loop.c b/util/main-loop.c index 65e5dbcc941b..e59af0e270e4 100644 --- a/util/main-loop.c +++ b/util/main-loop.c @@ -100,6 +100,7 @@ static int qemu_signal_init(Error **errp) sigaddset(&set, SIGIO); sigaddset(&set, SIGALRM); sigaddset(&set, SIGBUS); + sigaddset(&set, SIGWINCH); /* SIGINT cannot be handled via signalfd, so that ^C can be used * to interrupt QEMU when it is being run under gdb. SIGHUP and * SIGTERM are also handled asynchronously, even though it is not @@ -124,6 +125,38 @@ static int qemu_signal_init(Error **errp) return 0; } +static NotifierList sigwinch_notifiers = + NOTIFIER_LIST_INITIALIZER(sigwinch_notifiers); + +static void sigwinch_handler(int signum) +{ + notifier_list_notify(&sigwinch_notifiers, NULL); +} + +void sigwinch_add_notifier(Notifier *n) +{ + if (notifier_list_empty(&sigwinch_notifiers)) { + struct sigaction action = { + .sa_handler = sigwinch_handler, + }; + sigaction(SIGWINCH, &action, NULL); + } + + notifier_list_add(&sigwinch_notifiers, n); +} + +void sigwinch_remove_notifier(Notifier *n) +{ + notifier_remove(n); + + if (notifier_list_empty(&sigwinch_notifiers)) { + struct sigaction action = { + .sa_handler = SIG_DFL, + }; + sigaction(SIGWINCH, &action, NULL); + } +} + #else /* _WIN32 */ static int qemu_signal_init(Error **errp) -- 2.56.0.116.g6de20f6092dc
