1
0
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:
K.Takata
2022-06-17 20:05:40 +01:00
committed by Bram Moolenaar
parent 7d149f899d
commit f9f2a330b9
3 changed files with 69 additions and 40 deletions

View File

@@ -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,6 +35,7 @@ func s:EditElsewhere(filename)
endif endif
" Check if this server is editing our file. " Check if this server is editing our file.
try
if remote_expr(servername, "bufloaded('" . fname_esc . "')") if remote_expr(servername, "bufloaded('" . fname_esc . "')")
" Yes, bring it to the foreground. " Yes, bring it to the foreground.
if has("win32") if has("win32")
@@ -61,6 +62,9 @@ func s:EditElsewhere(filename)
endif endif
return 'q' return 'q'
endif endif
catch /^Vim\%((\a\+)\)\=:E241:/
" Unable to send to this server, ignore it.
endtry
endwhile endwhile
return '' return ''
endfunc endfunc

View File

@@ -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,
(LPARAM)(&data)))
return 0;
return -1; 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 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)

View File

@@ -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,
/**/ /**/