summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorK.Takata <kentkt@csc.jp>2022-06-17 20:05:40 +0100
committerBram Moolenaar <Bram@vim.org>2022-06-17 20:05:40 +0100
commitf9f2a330b961fe1623d428b61afdc52f0af0a666 (patch)
tree0dfa84d89fac5c70d3044db1e42e274752bb59e4
parent7d149f899d423b7bf2b90d7b11ebe3e560c462b9 (diff)
patch 8.2.5118: MS-Windows: sending a message to another Vim may hangv8.2.5118
Problem: MS-Windows: sending a message to another Vim may hang if that Vim is halted. Solution: Add a timeout to serverSendToVim(). (Ken Takata, closes #10585)
-rw-r--r--runtime/pack/dist/opt/editexisting/plugin/editexisting.vim50
-rw-r--r--src/os_mswin.c55
-rw-r--r--src/version.c2
3 files changed, 68 insertions, 39 deletions
diff --git a/runtime/pack/dist/opt/editexisting/plugin/editexisting.vim b/runtime/pack/dist/opt/editexisting/plugin/editexisting.vim
index d9877a0591..5eda29047d 100644
--- a/runtime/pack/dist/opt/editexisting/plugin/editexisting.vim
+++ b/runtime/pack/dist/opt/editexisting/plugin/editexisting.vim
@@ -1,6 +1,6 @@
" Vim Plugin: Edit the file with an existing Vim if possible
" Maintainer: Bram Moolenaar
-" Last Change: 2016 Mar 28
+" Last Change: 2022 Jun 17
" To use add ":packadd! editexisting" in your vimrc file.
@@ -35,32 +35,36 @@ func s:EditElsewhere(filename)
endif
" Check if this server is editing our file.
- if remote_expr(servername, "bufloaded('" . fname_esc . "')")
- " Yes, bring it to the foreground.
- if has("win32")
- call remote_foreground(servername)
- endif
- call remote_expr(servername, "foreground()")
+ try
+ if remote_expr(servername, "bufloaded('" . fname_esc . "')")
+ " Yes, bring it to the foreground.
+ if has("win32")
+ call remote_foreground(servername)
+ endif
+ call remote_expr(servername, "foreground()")
- if remote_expr(servername, "exists('*EditExisting')")
- " Make sure the file is visible in a window (not hidden).
- " If v:swapcommand exists and is set, send it to the server.
- if exists("v:swapcommand")
- let c = substitute(v:swapcommand, "'", "''", "g")
- call remote_expr(servername, "EditExisting('" . fname_esc . "', '" . c . "')")
- else
- call remote_expr(servername, "EditExisting('" . fname_esc . "', '')")
+ if remote_expr(servername, "exists('*EditExisting')")
+ " Make sure the file is visible in a window (not hidden).
+ " If v:swapcommand exists and is set, send it to the server.
+ if exists("v:swapcommand")
+ let c = substitute(v:swapcommand, "'", "''", "g")
+ call remote_expr(servername, "EditExisting('" . fname_esc . "', '" . c . "')")
+ else
+ call remote_expr(servername, "EditExisting('" . fname_esc . "', '')")
+ endif
endif
- endif
- if !(has('vim_starting') && has('gui_running') && has('gui_win32'))
- " Tell the user what is happening. Not when the GUI is starting
- " though, it would result in a message box.
- echomsg "File is being edited by " . servername
- sleep 2
+ if !(has('vim_starting') && has('gui_running') && has('gui_win32'))
+ " Tell the user what is happening. Not when the GUI is starting
+ " though, it would result in a message box.
+ echomsg "File is being edited by " . servername
+ sleep 2
+ endif
+ return 'q'
endif
- return 'q'
- endif
+ catch /^Vim\%((\a\+)\)\=:E241:/
+ " Unable to send to this server, ignore it.
+ endtry
endwhile
return ''
endfunc
diff --git a/src/os_mswin.c b/src/os_mswin.c
index 448b2bf29c..256da04580 100644
--- a/src/os_mswin.c
+++ b/src/os_mswin.c
@@ -1971,6 +1971,10 @@ HWND message_window = 0; // window that's handling messages
# define VIM_CLASSNAME "VIM_MESSAGES"
# define VIM_CLASSNAME_LEN (sizeof(VIM_CLASSNAME) - 1)
+// Timeout for sending a message to another Vim instance. Normally this works
+// instantly, but it may hang when the other Vim instance is halted.
+# define SENDMESSAGE_TIMEOUT (5 * 1000)
+
// Communication is via WM_COPYDATA messages. The message type is sent in
// the dwData parameter. Types are defined here.
# define COPYDATA_KEYS 0
@@ -1992,9 +1996,9 @@ static char_u *client_enc = NULL;
/*
* Tell the other side what encoding we are using.
- * Errors are ignored.
+ * Return -1 if timeout happens. Other errors are ignored.
*/
- static void
+ static int
serverSendEnc(HWND target)
{
COPYDATASTRUCT data;
@@ -2002,8 +2006,11 @@ serverSendEnc(HWND target)
data.dwData = COPYDATA_ENCODING;
data.cbData = (DWORD)STRLEN(p_enc) + 1;
data.lpData = p_enc;
- (void)SendMessage(target, WM_COPYDATA, (WPARAM)message_window,
- (LPARAM)(&data));
+ if (SendMessageTimeout(target, WM_COPYDATA,
+ (WPARAM)message_window, (LPARAM)&data,
+ SMTO_ABORTIFHUNG, SENDMESSAGE_TIMEOUT, NULL) == 0)
+ return -1;
+ return 0;
}
/*
@@ -2061,6 +2068,7 @@ Messaging_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
COPYDATASTRUCT reply;
char_u *res;
int retval;
+ DWORD_PTR dwret = 0;
char_u *str;
char_u *tofree;
@@ -2114,9 +2122,17 @@ Messaging_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
reply.lpData = res;
reply.cbData = (DWORD)STRLEN(res) + 1;
- serverSendEnc(sender);
- retval = (int)SendMessage(sender, WM_COPYDATA,
- (WPARAM)message_window, (LPARAM)(&reply));
+ if (serverSendEnc(sender) < 0)
+ retval = -1;
+ else
+ {
+ if (SendMessageTimeout(sender, WM_COPYDATA,
+ (WPARAM)message_window, (LPARAM)&reply,
+ SMTO_ABORTIFHUNG, SENDMESSAGE_TIMEOUT, &dwret) == 0)
+ retval = -1;
+ else
+ retval = (int)dwret;
+ }
vim_free(tofree);
vim_free(res);
return retval;
@@ -2394,6 +2410,7 @@ serverSendReply(
HWND target;
COPYDATASTRUCT data;
long_u n = 0;
+ DWORD_PTR dwret = 0;
// The "name" argument is a magic cookie obtained from expand("<client>").
// It should be of the form 0xXXXXX - i.e. a C hex literal, which is the
@@ -2410,12 +2427,13 @@ serverSendReply(
data.cbData = (DWORD)STRLEN(reply) + 1;
data.lpData = reply;
- serverSendEnc(target);
- if (SendMessage(target, WM_COPYDATA, (WPARAM)message_window,
- (LPARAM)(&data)))
- return 0;
-
- return -1;
+ if (serverSendEnc(target) < 0)
+ return -1;
+ if (SendMessageTimeout(target, WM_COPYDATA,
+ (WPARAM)message_window, (LPARAM)&data,
+ SMTO_ABORTIFHUNG, SENDMESSAGE_TIMEOUT, &dwret) == 0)
+ return -1;
+ return dwret ? 0 : -1;
}
int
@@ -2432,6 +2450,7 @@ serverSendToVim(
COPYDATASTRUCT data;
char_u *retval = NULL;
int retcode = 0;
+ DWORD_PTR dwret = 0;
char_u altname_buf[MAX_PATH];
// Execute locally if no display or target is ourselves
@@ -2463,9 +2482,13 @@ serverSendToVim(
data.cbData = (DWORD)STRLEN(cmd) + 1;
data.lpData = cmd;
- serverSendEnc(target);
- if (SendMessage(target, WM_COPYDATA, (WPARAM)message_window,
- (LPARAM)(&data)) == 0)
+ if (serverSendEnc(target) < 0)
+ return -1;
+ if (SendMessageTimeout(target, WM_COPYDATA,
+ (WPARAM)message_window, (LPARAM)&data,
+ SMTO_ABORTIFHUNG, SENDMESSAGE_TIMEOUT, &dwret) == 0)
+ return -1;
+ if (dwret == 0)
return -1;
if (asExpr)
diff --git a/src/version.c b/src/version.c
index 1b6fd28933..6ea4a379eb 100644
--- a/src/version.c
+++ b/src/version.c
@@ -735,6 +735,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 5118,
+/**/
5117,
/**/
5116,