From f9f2a330b961fe1623d428b61afdc52f0af0a666 Mon Sep 17 00:00:00 2001 From: "K.Takata" Date: Fri, 17 Jun 2022 20:05:40 +0100 Subject: 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) --- src/os_mswin.c | 55 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 16 deletions(-) (limited to 'src/os_mswin.c') 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(""). // 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) -- cgit v1.2.3