0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

patch 8.2.2586: process id may be invalid

Problem:    Process id may be invalid.
Solution:   Use sysinfo.uptime to check for recent reboot. (suggested by Hugo
            van der Sanden, closes #7947)
This commit is contained in:
Bram Moolenaar
2021-03-10 21:26:37 +01:00
parent c23555de34
commit f52f0606ed
8 changed files with 147 additions and 16 deletions

29
src/auto/configure vendored
View File

@@ -13918,6 +13918,35 @@ $as_echo "no" >&6; }
fi fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext 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 <sys/types.h>
#include <sys/sysinfo.h>
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 "$as_me:${as_lineno-$LINENO}: checking for sysconf" >&5
$as_echo_n "checking for sysconf... " >&6; } $as_echo_n "checking for sysconf... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext

View File

@@ -213,6 +213,7 @@
#undef HAVE_SYSCTL #undef HAVE_SYSCTL
#undef HAVE_SYSINFO #undef HAVE_SYSINFO
#undef HAVE_SYSINFO_MEM_UNIT #undef HAVE_SYSINFO_MEM_UNIT
#undef HAVE_SYSINFO_UPTIME
#undef HAVE_TGETENT #undef HAVE_TGETENT
#undef HAVE_TOWLOWER #undef HAVE_TOWLOWER
#undef HAVE_TOWUPPER #undef HAVE_TOWUPPER

View File

@@ -4095,6 +4095,20 @@ AC_TRY_COMPILE(
AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYSINFO_MEM_UNIT), AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYSINFO_MEM_UNIT),
AC_MSG_RESULT(no)) AC_MSG_RESULT(no))
dnl struct sysinfo may have the uptime field or not
AC_MSG_CHECKING(for sysinfo.uptime)
AC_TRY_COMPILE(
[#include <sys/types.h>
#include <sys/sysinfo.h>],
[ 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 dnl sysconf() may exist but not support what we want to use
AC_MSG_CHECKING(for sysconf) AC_MSG_CHECKING(for sysconf)
AC_TRY_COMPILE( AC_TRY_COMPILE(

View File

@@ -1860,6 +1860,7 @@ EXTERN int nfa_fail_for_testing INIT(= FALSE);
EXTERN int no_query_mouse_for_testing INIT(= FALSE); EXTERN int no_query_mouse_for_testing INIT(= FALSE);
EXTERN int ui_delay_for_testing INIT(= 0); EXTERN int ui_delay_for_testing INIT(= 0);
EXTERN int reset_term_props_on_termresponse INIT(= FALSE); EXTERN int reset_term_props_on_termresponse INIT(= FALSE);
EXTERN long override_sysinfo_uptime INIT(= -1);
EXTERN int in_free_unref_items INIT(= FALSE); EXTERN int in_free_unref_items INIT(= FALSE);
#endif #endif

View File

@@ -1080,6 +1080,32 @@ add_b0_fenc(
} }
} }
#if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO_UPTIME)
# include <sys/sysinfo.h>
#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. * Try to recover curbuf from the .swp file.
@@ -1692,7 +1718,7 @@ ml_recover(int checkext)
msg(_("Recovery completed. Buffer contents equals file contents.")); msg(_("Recovery completed. Buffer contents equals file contents."));
msg_puts(_("\nYou may want to delete the .swp file now.")); msg_puts(_("\nYou may want to delete the .swp file now."));
#if defined(UNIX) || defined(MSWIN) #if defined(UNIX) || defined(MSWIN)
if (mch_process_running(char_to_long(b0p->b0_pid))) if (swapfile_process_running(b0p, fname_used))
{ {
// Warn there could be an active Vim on the same file, the user may // Warn there could be an active Vim on the same file, the user may
// want to kill it. // want to kill it.
@@ -2170,7 +2196,7 @@ swapfile_info(char_u *fname)
msg_puts(_("\n process ID: ")); msg_puts(_("\n process ID: "));
msg_outnum(char_to_long(b0.b0_pid)); msg_outnum(char_to_long(b0.b0_pid));
#if defined(UNIX) || defined(MSWIN) #if defined(UNIX) || defined(MSWIN)
if (mch_process_running(char_to_long(b0.b0_pid))) if (swapfile_process_running(&b0, fname))
{ {
msg_puts(_(" (STILL RUNNING)")); msg_puts(_(" (STILL RUNNING)"));
# ifdef HAVE_PROCESS_STILL_RUNNING # ifdef HAVE_PROCESS_STILL_RUNNING
@@ -2213,9 +2239,6 @@ swapfile_unchanged(char_u *fname)
int fd; int fd;
struct block0 b0; struct block0 b0;
int ret = TRUE; int ret = TRUE;
#if defined(UNIX) || defined(MSWIN)
long pid;
#endif
// must be able to stat the swap file // must be able to stat the swap file
if (mch_stat((char *)fname, &st) == -1) if (mch_stat((char *)fname, &st) == -1)
@@ -2258,8 +2281,7 @@ swapfile_unchanged(char_u *fname)
} }
// process must be known and not be running // process must be known and not be running
pid = char_to_long(b0.b0_pid); if (char_to_long(b0.b0_pid) == 0L || swapfile_process_running(&b0, fname))
if (pid == 0L || mch_process_running(pid))
ret = FALSE; ret = FALSE;
#endif #endif

View File

@@ -1,5 +1,7 @@
" Test :recover " Test :recover
source check.vim
func Test_recover_root_dir() func Test_recover_root_dir()
" This used to access invalid memory. " This used to access invalid memory.
split Xtest split Xtest
@@ -21,6 +23,21 @@ func Test_recover_root_dir()
set dir& set dir&
endfunc 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 " 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. " blocks. Then recovers from the swap file and checks all text is restored.
" "
@@ -37,15 +54,9 @@ func Test_swap_file()
let i += 1 let i += 1
endwhile endwhile
$delete $delete
preserve
" get the name of the swap file let swname = CopySwapfile()
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 new
only! only!
bwipe! Xtest bwipe! Xtest
@@ -67,4 +78,52 @@ func Test_swap_file()
enew! | only enew! | only
endfunc 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: shiftwidth=2 sts=2 expandtab

View File

@@ -970,6 +970,8 @@ f_test_override(typval_T *argvars, typval_T *rettv UNUSED)
ui_delay_for_testing = val; ui_delay_for_testing = val;
else if (STRCMP(name, (char_u *)"term_props") == 0) else if (STRCMP(name, (char_u *)"term_props") == 0)
reset_term_props_on_termresponse = val; 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) else if (STRCMP(name, (char_u *)"ALL") == 0)
{ {
disable_char_avail_for_testing = FALSE; disable_char_avail_for_testing = FALSE;
@@ -979,6 +981,7 @@ f_test_override(typval_T *argvars, typval_T *rettv UNUSED)
no_query_mouse_for_testing = FALSE; no_query_mouse_for_testing = FALSE;
ui_delay_for_testing = 0; ui_delay_for_testing = 0;
reset_term_props_on_termresponse = FALSE; reset_term_props_on_termresponse = FALSE;
override_sysinfo_uptime = -1;
if (save_starting >= 0) if (save_starting >= 0)
{ {
starting = save_starting; starting = save_starting;

View File

@@ -750,6 +750,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
2586,
/**/ /**/
2585, 2585,
/**/ /**/