From 285377999fd52200f2ae352eced03351c3bce655 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 29 Sep 2023 05:00:43 -0400 Subject: [PATCH] Fix SEGFAULT at terminal resize this_cli is a thread-local variable used by functions within SIGWINCH signal handler. This means that it can only be accessed by the main thread (that created it). Previosly however this signal could be handled by any thread of the process, thus occasionally causing SEGFAULTs. In a multithreaded process if a signal is blocked by all threads but one, then the signal will be delivered to the thread expecting it. Using the fact that signal masks are inherited by pthreads this commit blocks SIGWINCH in the beginning of main(before the workers and the screen timer are spawned) and unblocks it just before cli_start(). The unblocking could be moved to scrn_start() function. An alternative to this could be adding a 'handle_winch' atomic to struct cli_scrn. Signed-off-by: Philipp --- app/pktgen-main.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/app/pktgen-main.c b/app/pktgen-main.c index 83d931cf..4a0d1e46 100644 --- a/app/pktgen-main.c +++ b/app/pktgen-main.c @@ -420,13 +420,26 @@ main(int argc, char **argv) { uint32_t i; int32_t ret; + struct sigaction sa; + sigset_t set; setlocale(LC_ALL, ""); - signal(SIGSEGV, sig_handler); - signal(SIGHUP, sig_handler); - signal(SIGINT, sig_handler); - signal(SIGPIPE, sig_handler); + sa.sa_handler = sig_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGPIPE, &sa, NULL); + + /* Block SIGWINCH for all threads, + * because we only want it to be + * handled by the main thread */ + sigemptyset(&set); + sigaddset(&set, SIGWINCH); + pthread_sigmask(SIG_BLOCK, &set, NULL); scrn_setw(1); /* Reset the window size, from possible crash run. */ scrn_pos(100, 1); /* Move the cursor to the bottom of the screen again */ @@ -561,6 +574,13 @@ main(int argc, char **argv) } pktgen_log_info("=== Run CLI\n"); + + /* Unblock SIGWINCH so main thread + * can handle screen resizes */ + sigemptyset(&set); + sigaddset(&set, SIGWINCH); + pthread_sigmask(SIG_BLOCK, &set, NULL); + cli_start(NULL); scrn_pause();