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:
29
src/auto/configure
vendored
29
src/auto/configure
vendored
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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(
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
|
@@ -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,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user