>From 5174f470b65a61496f66ff3227b8f2dea749fdc2 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sat, 27 Jun 2020 17:04:22 +0200 Subject: [PATCH] Fix invalid uses of siglongjmp. * poke/pk-repl.c (ctrlc_buf_valid): New variable. (poke_sigint_handler): If ctrlc_buf_valid is false, terminate the process. (pk_repl): Set ctrlc_buf_valid to false before installing the signal handler and to true while ctrlc_buf is valid. Move the sigsetjmp invocation out of the loop. --- poke/pk-repl.c | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/poke/pk-repl.c b/poke/pk-repl.c index 08505cb..38a53a5 100644 --- a/poke/pk-repl.c +++ b/poke/pk-repl.c @@ -37,7 +37,10 @@ #include "pk-utils.h" #include "pk-map.h" -static sigjmp_buf ctrlc_buf; +/* The non-local entry point for reentering the REPL. */ +static sigjmp_buf /*volatile*/ ctrlc_buf; +/* When nonzero, ctrlc_buf contains a valid value. */ +static int volatile ctrlc_buf_valid; /* This function is called repeatedly by the readline library, when generating potential command line completions. @@ -202,13 +205,28 @@ banner (void) } static void -poke_sigint_handler (int status) +poke_sigint_handler (int sig) { - rl_free_line_state (); - rl_cleanup_after_signal (); - rl_line_buffer[rl_point = rl_end = rl_mark = 0] = 0; - printf ("\n"); - siglongjmp (ctrlc_buf, 1); + if (ctrlc_buf_valid) + { + /* Abort the current command, and return to the REPL. */ + rl_free_line_state (); + rl_cleanup_after_signal (); + rl_line_buffer[rl_point = rl_end = rl_mark = 0] = 0; + printf ("\n"); + siglongjmp (ctrlc_buf, 1); + } + else + { + /* The default behaviour for SIGINT is to terminate the process. + Let's do that here. */ + struct sigaction sa; + sa.sa_handler = SIG_DFL; + sa.sa_flags = 0; + sigemptyset (&sa.sa_mask); + sigaction (SIGINT, &sa, NULL); + raise (SIGINT); + } } /* Return a copy of TEXT, with every instance of the space character @@ -272,11 +290,12 @@ pk_repl (void) banner (); /* Arrange for the current line to be cancelled on SIGINT. */ + ctrlc_buf_valid = 0; struct sigaction sa; sa.sa_handler = poke_sigint_handler; sa.sa_flags = 0; sigemptyset (&sa.sa_mask); - sigaction (SIGINT, &sa, 0); + sigaction (SIGINT, &sa, NULL); #if defined HAVE_READLINE_HISTORY_H char *poke_history = NULL; @@ -300,13 +319,14 @@ pk_repl (void) rl_filename_quote_characters = " "; rl_filename_quoting_function = escape_metacharacters; + sigsetjmp (ctrlc_buf, 1); + ctrlc_buf_valid = 1; + while (!poke_exit_p) { char *prompt; char *line; - while (sigsetjmp (ctrlc_buf, 1) != 0); - pk_term_flush (); rl_completion_entry_function = poke_completion_function; prompt = pk_prompt (); @@ -345,6 +365,8 @@ pk_repl (void) free (poke_history); } #endif + + ctrlc_buf_valid = 0; } static int saved_point; -- 2.7.4