diff options
author | dbivolaru <dbivolaru@jacobs-alumni.de> | 2021-12-29 19:41:47 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2021-12-29 19:41:47 +0000 |
commit | ab16ad33ba10dd12ff6660fa57b88f1a30ddd8ba (patch) | |
tree | 85f14e9648cb4131f50599c792afb620e6ef43b6 /src | |
parent | 94fb8274ca8c93a10102d41c8bcc848f75cb7334 (diff) |
patch 8.2.3941: SIGTSTP is not handledv8.2.3941
Problem: SIGTSTP is not handled.
Solution: Handle SIGTSTP like pressing CTRL-Z. (closes #9422)
Diffstat (limited to 'src')
-rw-r--r-- | src/ex_docmd.c | 3 | ||||
-rw-r--r-- | src/os_unix.c | 39 | ||||
-rw-r--r-- | src/proto/ex_docmd.pro | 1 | ||||
-rw-r--r-- | src/testdir/test_signals.vim | 52 | ||||
-rw-r--r-- | src/version.c | 2 |
5 files changed, 92 insertions, 5 deletions
diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 8f4f4aea5e..12824a9dc9 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -109,7 +109,6 @@ static void ex_pedit(exarg_T *eap); # define ex_pedit ex_ni #endif static void ex_hide(exarg_T *eap); -static void ex_stop(exarg_T *eap); static void ex_exit(exarg_T *eap); static void ex_print(exarg_T *eap); #ifdef FEAT_BYTEOFF @@ -6200,7 +6199,7 @@ ex_hide(exarg_T *eap UNUSED) /* * ":stop" and ":suspend": Suspend Vim. */ - static void + void ex_stop(exarg_T *eap) { /* diff --git a/src/os_unix.c b/src/os_unix.c index 77f35db958..e24c09f4aa 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -157,6 +157,11 @@ static void handle_resize(void); #if defined(SIGWINCH) static RETSIGTYPE sig_winch SIGPROTOARG; #endif +#if defined(SIGTSTP) +static RETSIGTYPE sig_tstp SIGPROTOARG; +// volatile because it is used in signal handler sig_tstp() and sigcont_handler(). +static volatile sig_atomic_t in_mch_suspend = FALSE; +#endif #if defined(SIGINT) static RETSIGTYPE catch_sigint SIGPROTOARG; #endif @@ -197,6 +202,8 @@ static int save_patterns(int num_pat, char_u **pat, int *num_file, char_u ***fil // volatile because it is used in signal handler sig_winch(). static volatile sig_atomic_t do_resize = FALSE; +// volatile because it is used in signal handler sig_tstp(). +static volatile sig_atomic_t got_tstp = FALSE; static char_u *extra_shell_arg = NULL; static int show_shell_mess = TRUE; // volatile because it is used in signal handler deathtrap(). @@ -851,6 +858,24 @@ sig_winch SIGDEFARG(sigarg) } #endif +#if defined(SIGTSTP) + static RETSIGTYPE +sig_tstp SIGDEFARG(sigarg) +{ + // Second time we get called we actually need to suspend + if (in_mch_suspend) + { + signal(SIGTSTP, ignore_sigtstp ? SIG_IGN : SIG_DFL); + raise(sigarg); + } + + // this is not required on all systems, but it doesn't hurt anybody + signal(SIGTSTP, (RETSIGTYPE (*)())sig_tstp); + got_tstp = TRUE; + SIGRETURN; +} +#endif + #if defined(SIGINT) static RETSIGTYPE catch_sigint SIGDEFARG(sigarg) @@ -1158,7 +1183,6 @@ after_sigcont(void) #if defined(SIGCONT) static RETSIGTYPE sigcont_handler SIGPROTOARG; -static volatile sig_atomic_t in_mch_suspend = FALSE; /* * With multi-threading, suspending might not work immediately. Catch the @@ -1353,7 +1377,7 @@ set_signals(void) #ifdef SIGTSTP // See mch_init() for the conditions under which we ignore SIGTSTP. - signal(SIGTSTP, ignore_sigtstp ? SIG_IGN : SIG_DFL); + signal(SIGTSTP, ignore_sigtstp ? SIG_IGN : (RETSIGTYPE (*)())sig_tstp); #endif #if defined(SIGCONT) signal(SIGCONT, sigcont_handler); @@ -6386,6 +6410,15 @@ select_eintr: # ifdef EINTR if (ret == -1 && errno == EINTR) { + // Check whether the EINTR is caused by SIGTSTP + if (got_tstp && !in_mch_suspend) + { + exarg_T ea; + ea.forceit = TRUE; + ex_stop(&ea); + got_tstp = FALSE; + } + // Check whether window has been resized, EINTR may be caused by // SIGWINCH. if (do_resize) @@ -7176,7 +7209,7 @@ gpm_open(void) // we are going to suspend or starting an external process // so we shouldn't have problem with this # ifdef SIGTSTP - signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL); + signal(SIGTSTP, restricted ? SIG_IGN : (RETSIGTYPE (*)())sig_tstp); # endif return 1; // succeed } diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro index d88b8a3e58..0fed2f02df 100644 --- a/src/proto/ex_docmd.pro +++ b/src/proto/ex_docmd.pro @@ -40,6 +40,7 @@ int before_quit_autocmds(win_T *wp, int quit_all, int forceit); void ex_quit(exarg_T *eap); void tabpage_close(int forceit); void tabpage_close_other(tabpage_T *tp, int forceit); +void ex_stop(exarg_T *eap); void handle_drop(int filec, char_u **filev, int split, void (*callback)(void *), void *cookie); void handle_any_postponed_drop(void); void ex_splitview(exarg_T *eap); diff --git a/src/testdir/test_signals.vim b/src/testdir/test_signals.vim index 72fd024332..d3a4d89cec 100644 --- a/src/testdir/test_signals.vim +++ b/src/testdir/test_signals.vim @@ -105,6 +105,58 @@ func Test_signal_INT() call StopVimInTerminal(buf) endfunc +" Test signal TSTP. Handler sets got_tstp. +func Test_signal_TSTP() + CheckRunVimInTerminal + if !HasSignal('TSTP') + throw 'Skipped: TSTP signal not supported' + endif + + " Skip the test when running with valgrind as signal TSTP is not received + " somehow by Vim when running with valgrind. + let cmd = GetVimCommand() + if cmd =~ 'valgrind' + throw 'Skipped: cannot test signal TSTP with valgrind' + endif + + " If test fails once, it can leave temporary files and trying to rerun + " the test would then fail again if they are not deleted first. + call delete('.Xsig_TERM.swp') + call delete('XsetupAucmd') + call delete('XautoOut') + let lines =<< trim END + au VimSuspend * call writefile(["VimSuspend triggered"], "XautoOut", "as") + au VimResume * call writefile(["VimResume triggered"], "XautoOut", "as") + END + call writefile(lines, 'XsetupAucmd') + + let buf = RunVimInTerminal('-S XsetupAucmd Xsig_TERM', {'rows': 6}) + let pid_vim = term_getjob(buf)->job_info().process + + call term_sendkeys(buf, ":call setline(1, 'foo')\n") + call WaitForAssert({-> assert_equal('foo', term_getline(buf, 1))}) + + call assert_false(filereadable('Xsig_TERM')) + + " After TSTP the file is not saved (same function as ^Z) + exe 'silent !kill -s TSTP ' .. pid_vim + call WaitForAssert({-> assert_true(filereadable('.Xsig_TERM.swp'))}) + + " We resume after the suspend + exe 'silent !kill -s CONT ' .. pid_vim + exe 'silent !sleep 0.006' + + call StopVimInTerminal(buf) + + let result = readfile('XautoOut') + call assert_equal(["VimSuspend triggered", "VimResume triggered"], result) + + %bwipe! + call delete('.Xsig_TERM.swp') + call delete('XsetupAucmd') + call delete('XautoOut') +endfunc + " Test a deadly signal. " " There are several deadly signals: SISEGV, SIBUS, SIGTERM... diff --git a/src/version.c b/src/version.c index ee3a29f514..2a5260a042 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3941, +/**/ 3940, /**/ 3939, |