aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/memline.c26
-rw-r--r--src/nvim/testdir/test_recover.vim79
2 files changed, 91 insertions, 14 deletions
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 02a7e1f697..955074e1f2 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -72,7 +72,7 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option.h"
-#include "nvim/os/fs_defs.h"
+#include "nvim/os/fs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.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.
///
/// @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_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
// want to kill it.
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) {
msg_puts(_("\n process ID: "));
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)"));
process_still_running = true;
}
@@ -1555,8 +1572,7 @@ static bool swapfile_unchanged(char *fname)
}
// process must be known and not running.
- long pid = char_to_long(b0.b0_pid);
- if (pid == 0L || os_proc_running((int)pid)) {
+ if (char_to_long(b0.b0_pid) == 0L || swapfile_process_running(&b0, fname)) {
ret = false;
}
diff --git a/src/nvim/testdir/test_recover.vim b/src/nvim/testdir/test_recover.vim
index fc073cacd2..c3bdde0d71 100644
--- a/src/nvim/testdir/test_recover.vim
+++ b/src/nvim/testdir/test_recover.vim
@@ -1,5 +1,7 @@
" Test :recover
+source check.vim
+
func Test_recover_root_dir()
" This used to access invalid memory.
split Xtest
@@ -23,6 +25,21 @@ func Test_recover_root_dir()
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.
"
@@ -40,15 +57,9 @@ func Test_swap_file()
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
+
+ let swname = CopySwapfile()
+
new
only!
bwipe! Xtest
@@ -69,3 +80,53 @@ func Test_swap_file()
set undolevels&
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