Replace Sleep by a Wait function that pumps messages

- The wait function optionally calls IsDialogMessage() if a dialog
  handle is specified. For other customizations the caller can
  install a WH_MSGFILTER hook. The hook will get called with
  nCode = MSGF_OVPN_WAIT and lParam = &msg.

- Use this in place of Sleep in main.c, scripts.c and PLAP dll.

Fixes #576

Signed-off-by: Selva Nair <selva.nair@gmail.com>
pull/608/head
Selva Nair 2023-01-10 17:29:44 -05:00
parent 141a687ddd
commit 2b1e5867f0
9 changed files with 78 additions and 24 deletions

9
main.c
View File

@ -376,11 +376,14 @@ StopAllOpenVPN()
}
}
/* Wait for all connections to terminate (Max 5 sec) */
for (i = 0; i < 20; i++, Sleep(250))
/* Wait for all connections to terminate (Max 20 rounds of 250 msec = 5 sec) */
for (i = 0; i < 20; i++)
{
if (CountConnState(disconnected) + CountConnState(detached) == o.num_configs)
if (CountConnState(disconnected) + CountConnState(detached) == o.num_configs
|| !OVPNMsgWait(250, NULL)) /* Quit received */
{
break;
}
}
}

2
main.h
View File

@ -65,6 +65,8 @@
#define WM_OVPN_STATE (WM_APP + 23)
#define WM_OVPN_DETACH (WM_APP + 24)
#define MSGF_OVPN_WAIT (MSGF_USER + 1)
/* bool definitions */
#define bool int
#define true 1

View File

@ -345,7 +345,7 @@ OnManagement(SOCKET sk, LPARAM lParam)
else if (strncmp(pos, "INFO:", 5) == 0)
{
/* delay until management interface accepts input */
Sleep(100);
OVPNMsgWait(100, c->hwndStatus);
c->manage.connected = 2;
if (rtmsg_handler[ready_])
rtmsg_handler[ready_](c, pos + 5);

36
misc.c
View File

@ -1046,3 +1046,39 @@ RunAsAdmin(const WCHAR *cmd, const WCHAR *params)
}
return status;
}
/* Like sleep but service messages. If hdlg is not NULL
* dialog messages for it are checked. Also services
* MSG_FILTER hooks if caller wants further special processing.
* Returns false on if WM_QUIT received else returns true (on timeout).
*/
bool
OVPNMsgWait(DWORD timeout, HWND hdlg)
{
ULONGLONG now = GetTickCount64();
ULONGLONG end = now + timeout;
while (end > now)
{
if (MsgWaitForMultipleObjectsEx(0, NULL, end - now, QS_ALLINPUT, MWMO_INPUTAVAILABLE) == WAIT_OBJECT_0)
{
MSG msg;
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
PostQuitMessage((int) msg.wParam);
return false;
}
else if (!CallMsgFilter(&msg, MSGF_OVPN_WAIT)
&& (!hdlg || !IsDialogMessage(hdlg, &msg)))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
now = GetTickCount64();
}
return true;
}

9
misc.h
View File

@ -150,4 +150,13 @@ DWORD SetPLAPRegistration(BOOL action);
*/
DWORD RunAsAdmin(const WCHAR *cmd, const WCHAR *params);
/**
* Wait for a timeout while pumping messages. If hdlg is not NULL
* IsDialogMessage(hdlg, ...) is checked before dispatching messages.
* caller can install a WH_MSGFILTER hook if any other special processing
* is necessary. The hook will get called with ncode = MSGF_OVPN_WAIT.
* @returns false if WM_QUIT was received, else returns true on timeout.
*/
bool OVPNMsgWait(DWORD timeout, HWND hdlg);
#endif

View File

@ -2753,7 +2753,7 @@ ReadLineFromStdOut(HANDLE hStdOut, char *line, DWORD size)
if (read == size)
return FALSE;
Sleep(100);
Sleep(100); /* called when no UI is yet initialized */
}
if (!ReadFile(hStdOut, line, len, &read, NULL) || read != len)

View File

@ -30,6 +30,8 @@
#include "resource.h"
#include "localization.h"
#include "openvpn-gui-res.h"
#include "main.h"
#include "misc.h"
/* A "class" that implements IConnectableCredentialProviderCredential */
@ -607,7 +609,7 @@ again:
ConnectHelper(oc->c);
Sleep(100);
OVPNMsgWait(100, NULL);
/* if not immediately connected, show a progress dialog with
* service state changes and retry/cancel options. Progress dialog

View File

@ -405,7 +405,7 @@ DetachAllOpenVPN()
{
break;
}
Sleep(100);
OVPNMsgWait(100, NULL);
}
for (connection_t *c = o.chead; c; c = c->next)
@ -481,7 +481,7 @@ DisconnectHelper(connection_t *c)
time_t timeout = time(NULL) + 5;
while (timeout > time(NULL) && c->state != onhold && c->state != disconnected)
{
Sleep(100);
OVPNMsgWait(100, NULL);
}
ShowWindowAsync(GetDlgItem(c->hwndStatus, ID_DISCONNECT), SW_HIDE);

View File

@ -94,17 +94,17 @@ RunPreconnectScript(connection_t *c)
NULL, c->config_dir, &si, &pi))
return;
/* Wait process without blocking msg pump */
for (i = 0; i <= (int) o.preconnectscript_timeout; i++)
{
if (!GetExitCodeProcess(pi.hProcess, &exit_code))
goto out;
if (exit_code != STILL_ACTIVE)
goto out;
Sleep(1000);
if (!GetExitCodeProcess(pi.hProcess, &exit_code)
|| exit_code != STILL_ACTIVE
|| !OVPNMsgWait(1000, NULL))
{
break;
}
}
out:
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
if (logfile_handle != NULL)
@ -180,7 +180,7 @@ RunConnectScript(connection_t *c, int run_as_service)
{
if (!GetExitCodeProcess(pi.hProcess, &exit_code))
{
ShowLocalizedMsg(IDS_ERR_GET_EXIT_CODE, cmdline);
ShowLocalizedMsgEx(MB_OK|MB_ICONERROR, c->hwndStatus, TEXT(PACKAGE_NAME), IDS_ERR_GET_EXIT_CODE, cmdline);
goto out;
}
@ -191,7 +191,10 @@ RunConnectScript(connection_t *c, int run_as_service)
goto out;
}
Sleep(1000);
if (!OVPNMsgWait(1000, c->hwndStatus)) /* WM_QUIT -- do not popup error */
{
goto out;
}
}
ShowLocalizedMsgEx(MB_OK|MB_ICONERROR, c->hwndStatus, TEXT(PACKAGE_NAME), IDS_ERR_RUN_CONN_SCRIPT_TIMEOUT, o.connectscript_timeout);
@ -266,13 +269,12 @@ RunDisconnectScript(connection_t *c, int run_as_service)
for (i = 0; i <= (int) o.disconnectscript_timeout; i++)
{
if (!GetExitCodeProcess(pi.hProcess, &exit_code))
if (!GetExitCodeProcess(pi.hProcess, &exit_code)
|| exit_code != STILL_ACTIVE
|| !OVPNMsgWait(1000, c->hwndStatus)) /* WM_QUIT -- do not popup error */
{
goto out;
if (exit_code != STILL_ACTIVE)
goto out;
Sleep(1000);
}
}
out:
free(env);