forked from aniani/vim
patch 8.2.5118: MS-Windows: sending a message to another Vim may hang
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)
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
" Vim Plugin: Edit the file with an existing Vim if possible
|
" Vim Plugin: Edit the file with an existing Vim if possible
|
||||||
" Maintainer: Bram Moolenaar
|
" Maintainer: Bram Moolenaar
|
||||||
" Last Change: 2016 Mar 28
|
" Last Change: 2022 Jun 17
|
||||||
|
|
||||||
" To use add ":packadd! editexisting" in your vimrc file.
|
" To use add ":packadd! editexisting" in your vimrc file.
|
||||||
|
|
||||||
@@ -35,32 +35,36 @@ func s:EditElsewhere(filename)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
" Check if this server is editing our file.
|
" Check if this server is editing our file.
|
||||||
if remote_expr(servername, "bufloaded('" . fname_esc . "')")
|
try
|
||||||
" Yes, bring it to the foreground.
|
if remote_expr(servername, "bufloaded('" . fname_esc . "')")
|
||||||
if has("win32")
|
" Yes, bring it to the foreground.
|
||||||
call remote_foreground(servername)
|
if has("win32")
|
||||||
endif
|
call remote_foreground(servername)
|
||||||
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 . "', '')")
|
|
||||||
endif
|
endif
|
||||||
endif
|
call remote_expr(servername, "foreground()")
|
||||||
|
|
||||||
if !(has('vim_starting') && has('gui_running') && has('gui_win32'))
|
if remote_expr(servername, "exists('*EditExisting')")
|
||||||
" Tell the user what is happening. Not when the GUI is starting
|
" Make sure the file is visible in a window (not hidden).
|
||||||
" though, it would result in a message box.
|
" If v:swapcommand exists and is set, send it to the server.
|
||||||
echomsg "File is being edited by " . servername
|
if exists("v:swapcommand")
|
||||||
sleep 2
|
let c = substitute(v:swapcommand, "'", "''", "g")
|
||||||
|
call remote_expr(servername, "EditExisting('" . fname_esc . "', '" . c . "')")
|
||||||
|
else
|
||||||
|
call remote_expr(servername, "EditExisting('" . fname_esc . "', '')")
|
||||||
|
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
|
||||||
|
endif
|
||||||
|
return 'q'
|
||||||
endif
|
endif
|
||||||
return 'q'
|
catch /^Vim\%((\a\+)\)\=:E241:/
|
||||||
endif
|
" Unable to send to this server, ignore it.
|
||||||
|
endtry
|
||||||
endwhile
|
endwhile
|
||||||
return ''
|
return ''
|
||||||
endfunc
|
endfunc
|
||||||
|
@@ -1971,6 +1971,10 @@ HWND message_window = 0; // window that's handling messages
|
|||||||
# define VIM_CLASSNAME "VIM_MESSAGES"
|
# define VIM_CLASSNAME "VIM_MESSAGES"
|
||||||
# define VIM_CLASSNAME_LEN (sizeof(VIM_CLASSNAME) - 1)
|
# 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
|
// Communication is via WM_COPYDATA messages. The message type is sent in
|
||||||
// the dwData parameter. Types are defined here.
|
// the dwData parameter. Types are defined here.
|
||||||
# define COPYDATA_KEYS 0
|
# define COPYDATA_KEYS 0
|
||||||
@@ -1992,9 +1996,9 @@ static char_u *client_enc = NULL;
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Tell the other side what encoding we are using.
|
* 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)
|
serverSendEnc(HWND target)
|
||||||
{
|
{
|
||||||
COPYDATASTRUCT data;
|
COPYDATASTRUCT data;
|
||||||
@@ -2002,8 +2006,11 @@ serverSendEnc(HWND target)
|
|||||||
data.dwData = COPYDATA_ENCODING;
|
data.dwData = COPYDATA_ENCODING;
|
||||||
data.cbData = (DWORD)STRLEN(p_enc) + 1;
|
data.cbData = (DWORD)STRLEN(p_enc) + 1;
|
||||||
data.lpData = p_enc;
|
data.lpData = p_enc;
|
||||||
(void)SendMessage(target, WM_COPYDATA, (WPARAM)message_window,
|
if (SendMessageTimeout(target, WM_COPYDATA,
|
||||||
(LPARAM)(&data));
|
(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;
|
COPYDATASTRUCT reply;
|
||||||
char_u *res;
|
char_u *res;
|
||||||
int retval;
|
int retval;
|
||||||
|
DWORD_PTR dwret = 0;
|
||||||
char_u *str;
|
char_u *str;
|
||||||
char_u *tofree;
|
char_u *tofree;
|
||||||
|
|
||||||
@@ -2114,9 +2122,17 @@ Messaging_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||||||
reply.lpData = res;
|
reply.lpData = res;
|
||||||
reply.cbData = (DWORD)STRLEN(res) + 1;
|
reply.cbData = (DWORD)STRLEN(res) + 1;
|
||||||
|
|
||||||
serverSendEnc(sender);
|
if (serverSendEnc(sender) < 0)
|
||||||
retval = (int)SendMessage(sender, WM_COPYDATA,
|
retval = -1;
|
||||||
(WPARAM)message_window, (LPARAM)(&reply));
|
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(tofree);
|
||||||
vim_free(res);
|
vim_free(res);
|
||||||
return retval;
|
return retval;
|
||||||
@@ -2394,6 +2410,7 @@ serverSendReply(
|
|||||||
HWND target;
|
HWND target;
|
||||||
COPYDATASTRUCT data;
|
COPYDATASTRUCT data;
|
||||||
long_u n = 0;
|
long_u n = 0;
|
||||||
|
DWORD_PTR dwret = 0;
|
||||||
|
|
||||||
// The "name" argument is a magic cookie obtained from expand("<client>").
|
// 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
|
// 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.cbData = (DWORD)STRLEN(reply) + 1;
|
||||||
data.lpData = reply;
|
data.lpData = reply;
|
||||||
|
|
||||||
serverSendEnc(target);
|
if (serverSendEnc(target) < 0)
|
||||||
if (SendMessage(target, WM_COPYDATA, (WPARAM)message_window,
|
return -1;
|
||||||
(LPARAM)(&data)))
|
if (SendMessageTimeout(target, WM_COPYDATA,
|
||||||
return 0;
|
(WPARAM)message_window, (LPARAM)&data,
|
||||||
|
SMTO_ABORTIFHUNG, SENDMESSAGE_TIMEOUT, &dwret) == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
return dwret ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -2432,6 +2450,7 @@ serverSendToVim(
|
|||||||
COPYDATASTRUCT data;
|
COPYDATASTRUCT data;
|
||||||
char_u *retval = NULL;
|
char_u *retval = NULL;
|
||||||
int retcode = 0;
|
int retcode = 0;
|
||||||
|
DWORD_PTR dwret = 0;
|
||||||
char_u altname_buf[MAX_PATH];
|
char_u altname_buf[MAX_PATH];
|
||||||
|
|
||||||
// Execute locally if no display or target is ourselves
|
// Execute locally if no display or target is ourselves
|
||||||
@@ -2463,9 +2482,13 @@ serverSendToVim(
|
|||||||
data.cbData = (DWORD)STRLEN(cmd) + 1;
|
data.cbData = (DWORD)STRLEN(cmd) + 1;
|
||||||
data.lpData = cmd;
|
data.lpData = cmd;
|
||||||
|
|
||||||
serverSendEnc(target);
|
if (serverSendEnc(target) < 0)
|
||||||
if (SendMessage(target, WM_COPYDATA, (WPARAM)message_window,
|
return -1;
|
||||||
(LPARAM)(&data)) == 0)
|
if (SendMessageTimeout(target, WM_COPYDATA,
|
||||||
|
(WPARAM)message_window, (LPARAM)&data,
|
||||||
|
SMTO_ABORTIFHUNG, SENDMESSAGE_TIMEOUT, &dwret) == 0)
|
||||||
|
return -1;
|
||||||
|
if (dwret == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (asExpr)
|
if (asExpr)
|
||||||
|
@@ -734,6 +734,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 */
|
||||||
|
/**/
|
||||||
|
5118,
|
||||||
/**/
|
/**/
|
||||||
5117,
|
5117,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user