To: vim_dev@googlegroups.com Subject: Patch 8.2.3941 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3941 Problem: SIGTSTP is not handled. Solution: Handle SIGTSTP like pressing CTRL-Z. (closes #9422) Files: runtime/doc/autocmd.txt, src/ex_docmd.c, src/os_unix.c, src/proto/ex_docmd.pro, src/testdir/test_signals.vim *** ../vim-8.2.3940/runtime/doc/autocmd.txt 2021-11-13 12:38:45.534835910 +0000 --- runtime/doc/autocmd.txt 2021-12-29 19:38:03.626742672 +0000 *************** *** 1275,1282 **** :autocmd VimResume * checktime < *VimSuspend* VimSuspend When the Vim instance is suspended. Only when ! CTRL-Z was typed inside Vim, not when the ! SIGSTOP or SIGTSTP signal was sent to Vim. *WinClosed* WinClosed After closing a window. The pattern is matched against the |window-ID|. Both --- 1279,1286 ---- :autocmd VimResume * checktime < *VimSuspend* VimSuspend When the Vim instance is suspended. Only when ! CTRL-Z was typed inside Vim, or when the SIGTSTP ! signal was sent to Vim, but not for SIGSTOP. *WinClosed* WinClosed After closing a window. The pattern is matched against the |window-ID|. Both *** ../vim-8.2.3940/src/ex_docmd.c 2021-12-29 14:39:04.634256171 +0000 --- src/ex_docmd.c 2021-12-29 19:38:03.626742672 +0000 *************** *** 109,115 **** # 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 --- 109,114 ---- *************** *** 6200,6206 **** /* * ":stop" and ":suspend": Suspend Vim. */ ! static void ex_stop(exarg_T *eap) { /* --- 6199,6205 ---- /* * ":stop" and ":suspend": Suspend Vim. */ ! void ex_stop(exarg_T *eap) { /* *** ../vim-8.2.3940/src/os_unix.c 2021-12-27 17:21:38.016449116 +0000 --- src/os_unix.c 2021-12-29 19:38:03.626742672 +0000 *************** *** 157,162 **** --- 157,167 ---- #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,202 **** --- 202,209 ---- // 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,856 **** --- 858,881 ---- } #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,1164 **** #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 --- 1183,1188 ---- *************** *** 1353,1359 **** #ifdef SIGTSTP // See mch_init() for the conditions under which we ignore SIGTSTP. ! signal(SIGTSTP, ignore_sigtstp ? SIG_IGN : SIG_DFL); #endif #if defined(SIGCONT) signal(SIGCONT, sigcont_handler); --- 1377,1383 ---- #ifdef SIGTSTP // See mch_init() for the conditions under which we ignore SIGTSTP. ! signal(SIGTSTP, ignore_sigtstp ? SIG_IGN : (RETSIGTYPE (*)())sig_tstp); #endif #if defined(SIGCONT) signal(SIGCONT, sigcont_handler); *************** *** 6386,6391 **** --- 6410,6424 ---- # 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,7182 **** // 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); # endif return 1; // succeed } --- 7209,7215 ---- // 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 : (RETSIGTYPE (*)())sig_tstp); # endif return 1; // succeed } *** ../vim-8.2.3940/src/proto/ex_docmd.pro 2021-12-01 15:22:53.106902067 +0000 --- src/proto/ex_docmd.pro 2021-12-29 19:38:03.630742665 +0000 *************** *** 40,45 **** --- 40,46 ---- 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); *** ../vim-8.2.3940/src/testdir/test_signals.vim 2021-01-02 15:53:08.294010035 +0000 --- src/testdir/test_signals.vim 2021-12-29 19:38:03.630742665 +0000 *************** *** 105,110 **** --- 105,162 ---- 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... *** ../vim-8.2.3940/src/version.c 2021-12-29 19:22:19.136139687 +0000 --- src/version.c 2021-12-29 19:39:27.458612212 +0000 *************** *** 751,752 **** --- 751,754 ---- { /* Add new patch number below this line */ + /**/ + 3941, /**/ -- hundred-and-one symptoms of being an internet addict: 146. You experience ACTUAL physical withdrawal symptoms when away from your 'puter and the net. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///