To: vim_dev@googlegroups.com Subject: Patch 8.2.2586 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.2586 Problem: Process id may be invalid. Solution: Use sysinfo.uptime to check for recent reboot. (suggested by Hugo van der Sanden, closes #7947) Files: src/configure.ac, src/auto/configure, src/config.h.in, src/memline.c, src/testing.c, src/globals.h, src/testdir/test_recover.vim *** ../vim-8.2.2585/src/configure.ac 2021-02-25 17:17:51.625163951 +0100 --- src/configure.ac 2021-03-10 20:07:08.119062203 +0100 *************** *** 4095,4100 **** --- 4095,4114 ---- AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYSINFO_MEM_UNIT), AC_MSG_RESULT(no)) + dnl struct sysinfo may have the uptime field or not + AC_MSG_CHECKING(for sysinfo.uptime) + AC_TRY_COMPILE( + [#include + #include ], + [ struct sysinfo sinfo; + long ut; + + (void)sysinfo(&sinfo); + ut = sinfo.uptime; + ], + AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYSINFO_UPTIME), + AC_MSG_RESULT(no)) + dnl sysconf() may exist but not support what we want to use AC_MSG_CHECKING(for sysconf) AC_TRY_COMPILE( *** ../vim-8.2.2585/src/auto/configure 2021-02-25 17:17:51.629163935 +0100 --- src/auto/configure 2021-03-10 20:07:12.987052989 +0100 *************** *** 13918,13923 **** --- 13918,13952 ---- fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysinfo.uptime" >&5 + $as_echo_n "checking for sysinfo.uptime... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext + /* end confdefs.h. */ + #include + #include + int + main () + { + struct sysinfo sinfo; + long ut; + + (void)sysinfo(&sinfo); + ut = sinfo.uptime; + + ; + return 0; + } + _ACEOF + if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + $as_echo "yes" >&6; }; $as_echo "#define HAVE_SYSINFO_UPTIME 1" >>confdefs.h + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + $as_echo "no" >&6; } + fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysconf" >&5 $as_echo_n "checking for sysconf... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext *** ../vim-8.2.2585/src/config.h.in 2021-02-25 17:17:51.625163951 +0100 --- src/config.h.in 2021-03-10 20:06:14.155175800 +0100 *************** *** 213,218 **** --- 213,219 ---- #undef HAVE_SYSCTL #undef HAVE_SYSINFO #undef HAVE_SYSINFO_MEM_UNIT + #undef HAVE_SYSINFO_UPTIME #undef HAVE_TGETENT #undef HAVE_TOWLOWER #undef HAVE_TOWUPPER *** ../vim-8.2.2585/src/memline.c 2021-01-30 17:16:24.644042685 +0100 --- src/memline.c 2021-03-10 20:43:17.658722815 +0100 *************** *** 1080,1085 **** --- 1080,1111 ---- } } + #if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO_UPTIME) + # include + #endif + + /* + * Return TRUE if the process with number "b0p->b0_pid" is still running. + * "swap_fname" is the name of the swap file, if it's from before a reboot then + * the result is FALSE; + */ + static int + swapfile_process_running(ZERO_BL *b0p, char_u *swap_fname UNUSED) + { + #ifdef HAVE_SYSINFO_UPTIME + stat_T st; + struct sysinfo sinfo; + + // If the system rebooted after when the swap file was written then the + // process can't be running now. + if (mch_stat((char *)swap_fname, &st) != -1 + && sysinfo(&sinfo) == 0 + && st.st_mtime < time(NULL) - (override_sysinfo_uptime >= 0 + ? override_sysinfo_uptime : sinfo.uptime)) + return FALSE; + #endif + return mch_process_running(char_to_long(b0p->b0_pid)); + } /* * Try to recover curbuf from the .swp file. *************** *** 1692,1698 **** msg(_("Recovery completed. Buffer contents equals file contents.")); msg_puts(_("\nYou may want to delete the .swp file now.")); #if defined(UNIX) || defined(MSWIN) ! if (mch_process_running(char_to_long(b0p->b0_pid))) { // Warn there could be an active Vim on the same file, the user may // want to kill it. --- 1718,1724 ---- msg(_("Recovery completed. Buffer contents equals file contents.")); msg_puts(_("\nYou may want to delete the .swp file now.")); #if defined(UNIX) || defined(MSWIN) ! if (swapfile_process_running(b0p, fname_used)) { // Warn there could be an active Vim on the same file, the user may // want to kill it. *************** *** 2170,2176 **** msg_puts(_("\n process ID: ")); msg_outnum(char_to_long(b0.b0_pid)); #if defined(UNIX) || defined(MSWIN) ! if (mch_process_running(char_to_long(b0.b0_pid))) { msg_puts(_(" (STILL RUNNING)")); # ifdef HAVE_PROCESS_STILL_RUNNING --- 2196,2202 ---- msg_puts(_("\n process ID: ")); msg_outnum(char_to_long(b0.b0_pid)); #if defined(UNIX) || defined(MSWIN) ! if (swapfile_process_running(&b0, fname)) { msg_puts(_(" (STILL RUNNING)")); # ifdef HAVE_PROCESS_STILL_RUNNING *************** *** 2213,2221 **** int fd; struct block0 b0; int ret = TRUE; - #if defined(UNIX) || defined(MSWIN) - long pid; - #endif // must be able to stat the swap file if (mch_stat((char *)fname, &st) == -1) --- 2239,2244 ---- *************** *** 2258,2265 **** } // process must be known and not be running ! pid = char_to_long(b0.b0_pid); ! if (pid == 0L || mch_process_running(pid)) ret = FALSE; #endif --- 2281,2287 ---- } // process must be known and not be running ! if (char_to_long(b0.b0_pid) == 0L || swapfile_process_running(&b0, fname)) ret = FALSE; #endif *** ../vim-8.2.2585/src/testing.c 2020-11-04 15:07:13.057780706 +0100 --- src/testing.c 2021-03-10 20:38:25.331451725 +0100 *************** *** 970,975 **** --- 970,977 ---- ui_delay_for_testing = val; else if (STRCMP(name, (char_u *)"term_props") == 0) reset_term_props_on_termresponse = val; + else if (STRCMP(name, (char_u *)"uptime") == 0) + override_sysinfo_uptime = val; else if (STRCMP(name, (char_u *)"ALL") == 0) { disable_char_avail_for_testing = FALSE; *************** *** 979,984 **** --- 981,987 ---- no_query_mouse_for_testing = FALSE; ui_delay_for_testing = 0; reset_term_props_on_termresponse = FALSE; + override_sysinfo_uptime = -1; if (save_starting >= 0) { starting = save_starting; *** ../vim-8.2.2585/src/globals.h 2021-02-17 13:14:03.684013291 +0100 --- src/globals.h 2021-03-10 20:40:21.703215958 +0100 *************** *** 1860,1865 **** --- 1860,1866 ---- EXTERN int no_query_mouse_for_testing INIT(= FALSE); EXTERN int ui_delay_for_testing INIT(= 0); EXTERN int reset_term_props_on_termresponse INIT(= FALSE); + EXTERN long override_sysinfo_uptime INIT(= -1); EXTERN int in_free_unref_items INIT(= FALSE); #endif *** ../vim-8.2.2585/src/testdir/test_recover.vim 2020-08-12 18:50:31.883655785 +0200 --- src/testdir/test_recover.vim 2021-03-10 21:24:18.217132325 +0100 *************** *** 1,5 **** --- 1,7 ---- " Test :recover + source check.vim + func Test_recover_root_dir() " This used to access invalid memory. split Xtest *************** *** 21,26 **** --- 23,43 ---- set dir& endfunc + " Make a copy of the current swap file to "Xswap". + " Return the name of the swap file. + func CopySwapfile() + preserve + " get the name of the swap file + let swname = split(execute("swapname"))[0] + let swname = substitute(swname, '[[:blank:][:cntrl:]]*\(.\{-}\)[[:blank:][:cntrl:]]*$', '\1', '') + " make a copy of the swap file in Xswap + set binary + exe 'sp ' . swname + w! Xswap + set nobinary + return swname + endfunc + " Inserts 10000 lines with text to fill the swap file with two levels of pointer " blocks. Then recovers from the swap file and checks all text is restored. " *************** *** 37,51 **** let i += 1 endwhile $delete ! preserve ! " get the name of the swap file ! let swname = split(execute("swapname"))[0] ! let swname = substitute(swname, '[[:blank:][:cntrl:]]*\(.\{-}\)[[:blank:][:cntrl:]]*$', '\1', '') ! " make a copy of the swap file in Xswap ! set binary ! exe 'sp ' . swname ! w! Xswap ! set nobinary new only! bwipe! Xtest --- 54,62 ---- let i += 1 endwhile $delete ! ! let swname = CopySwapfile() ! new only! bwipe! Xtest *************** *** 67,70 **** --- 78,129 ---- enew! | only endfunc + func Test_nocatch_process_still_running() + " assume Unix means sysinfo.uptime can be used + CheckUnix + CheckNotGui + + " don't intercept existing swap file here + au! SwapExists + + " Edit a file and grab its swapfile. + edit Xswaptest + call setline(1, ['a', 'b', 'c']) + let swname = CopySwapfile() + + " Forget we edited this file + new + only! + bwipe! Xswaptest + + call rename('Xswap', swname) + call feedkeys('e', 'tL') + redir => editOutput + edit Xswaptest + redir END + call assert_match('E325: ATTENTION', editOutput) + call assert_match('file name: .*Xswaptest', editOutput) + call assert_match('process ID: \d* (STILL RUNNING)', editOutput) + + " Forget we edited this file + new + only! + bwipe! Xswaptest + + " pretend we rebooted + call test_override("uptime", 0) + sleep 1 + + call rename('Xswap', swname) + call feedkeys('e', 'tL') + redir => editOutput + edit Xswaptest + redir END + call assert_match('E325: ATTENTION', editOutput) + call assert_notmatch('(STILL RUNNING)', editOutput) + + call test_override("ALL", 0) + call delete(swname) + endfunc + " vim: shiftwidth=2 sts=2 expandtab *** ../vim-8.2.2585/src/version.c 2021-03-10 19:04:04.218736962 +0100 --- src/version.c 2021-03-10 20:41:53.490987269 +0100 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 2586, /**/ -- OLD WOMAN: King of the WHO? ARTHUR: The Britons. OLD WOMAN: Who are the Britons? "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///