mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
vim-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 vim/vim#7947)
f52f0606ed
test_override() is N/A.
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
@@ -72,7 +72,7 @@
|
|||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/message.h"
|
#include "nvim/message.h"
|
||||||
#include "nvim/option.h"
|
#include "nvim/option.h"
|
||||||
#include "nvim/os/fs_defs.h"
|
#include "nvim/os/fs.h"
|
||||||
#include "nvim/os/input.h"
|
#include "nvim/os/input.h"
|
||||||
#include "nvim/os/os.h"
|
#include "nvim/os/os.h"
|
||||||
#include "nvim/os/process.h"
|
#include "nvim/os/process.h"
|
||||||
@@ -698,6 +698,23 @@ static void add_b0_fenc(ZERO_BL *b0p, buf_T *buf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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 bool swapfile_process_running(const ZERO_BL *b0p, const char *swap_fname)
|
||||||
|
{
|
||||||
|
FileInfo st;
|
||||||
|
double uptime;
|
||||||
|
// If the system rebooted after when the swap file was written then the
|
||||||
|
// process can't be running now.
|
||||||
|
if (os_fileinfo(swap_fname, &st)
|
||||||
|
&& uv_uptime(&uptime) == 0
|
||||||
|
&& (Timestamp)st.stat.st_mtim.tv_sec < os_time() - (Timestamp)uptime) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return os_proc_running((int)char_to_long(b0p->b0_pid));
|
||||||
|
}
|
||||||
|
|
||||||
/// Try to recover curbuf from the .swp file.
|
/// Try to recover curbuf from the .swp file.
|
||||||
///
|
///
|
||||||
/// @param checkext if true, check the extension and detect whether it is a
|
/// @param checkext if true, check the extension and detect whether it is a
|
||||||
@@ -1139,7 +1156,7 @@ void ml_recover(bool 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 (os_proc_running((int)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.
|
||||||
msg_puts(_("\nNote: process STILL RUNNING: "));
|
msg_puts(_("\nNote: process STILL RUNNING: "));
|
||||||
@@ -1485,7 +1502,7 @@ static time_t swapfile_info(char_u *fname)
|
|||||||
if (char_to_long(b0.b0_pid) != 0L) {
|
if (char_to_long(b0.b0_pid) != 0L) {
|
||||||
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 (os_proc_running((int)char_to_long(b0.b0_pid))) {
|
if (swapfile_process_running(&b0, (const char *)fname)) {
|
||||||
msg_puts(_(" (STILL RUNNING)"));
|
msg_puts(_(" (STILL RUNNING)"));
|
||||||
process_still_running = true;
|
process_still_running = true;
|
||||||
}
|
}
|
||||||
@@ -1555,8 +1572,7 @@ static bool swapfile_unchanged(char *fname)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// process must be known and not running.
|
// process must be known and not running.
|
||||||
long pid = char_to_long(b0.b0_pid);
|
if (char_to_long(b0.b0_pid) == 0L || swapfile_process_running(&b0, fname)) {
|
||||||
if (pid == 0L || os_proc_running((int)pid)) {
|
|
||||||
ret = false;
|
ret = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
@@ -23,6 +25,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.
|
||||||
"
|
"
|
||||||
@@ -40,15 +57,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
|
||||||
@@ -69,3 +80,53 @@ func Test_swap_file()
|
|||||||
set undolevels&
|
set undolevels&
|
||||||
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
|
||||||
|
Reference in New Issue
Block a user