mirror of
https://github.com/OpenVPN/openvpn.git
synced 2026-05-28 04:03:29 -04:00
Fix signal handling on Windows
- In win32_signal_get() re-order the check so that Windows signals are picked up even if signal_received is non-zero - When management is not active, management_sleep() becomes sleep() but it is not interruptible by signals on Windows. Fix this by periodically checking for signal. Trac: #311 #639 (windows specific part) Github: Fixes OpenVPN/openvpn#205 (windows specific part) Note: if stuck in address resolution, press ctrl-C and wait for getaddrinfo() to timeout. v2: WIN32 --> _WIN32 add a chunk in management_sleep that was missed by sloppy conflict-resolution v3: following review by Lev Stipakov <lstipakov@gmail.com> win32_sleep() - Early fallback to Sleep() if no wait handles -- less indentation - Check signal only if wait-object triggered - Exit the while loop if not safe to continue Behaviour of win32_sleep(0) checking signal is retained though may be redundant v4: Avoid Sleep(0) and never loop back to wait again if wait-failed Signed-off-by: Selva Nair <selva.nair@gmail.com> Acked-by: Lev Stipakov <lstipakov@gmail.com> Message-Id: <20230106005438.1664046-1-selva.nair@gmail.com> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg25895.html Signed-off-by: Gert Doering <gert@greenie.muc.de>
This commit is contained in:
parent
dd66958198
commit
22977577ed
3 changed files with 92 additions and 40 deletions
|
|
@ -4117,9 +4117,16 @@ management_sleep(const int n)
|
|||
{
|
||||
management_event_loop_n_seconds(management, n);
|
||||
}
|
||||
else if (n > 0)
|
||||
else
|
||||
{
|
||||
sleep(n);
|
||||
#ifdef _WIN32
|
||||
win32_sleep(n);
|
||||
#else
|
||||
if (n > 0)
|
||||
{
|
||||
sleep(n);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4160,13 +4167,18 @@ man_persist_client_stats(struct management *man, struct context *c)
|
|||
|
||||
#else /* ifdef ENABLE_MANAGEMENT */
|
||||
|
||||
#include "win32.h"
|
||||
void
|
||||
management_sleep(const int n)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
win32_sleep(n);
|
||||
#else
|
||||
if (n > 0)
|
||||
{
|
||||
sleep(n);
|
||||
}
|
||||
#endif /* ifdef _WIN32 */
|
||||
}
|
||||
|
||||
#endif /* ENABLE_MANAGEMENT */
|
||||
|
|
|
|||
|
|
@ -642,50 +642,44 @@ int
|
|||
win32_signal_get(struct win32_signal *ws)
|
||||
{
|
||||
int ret = 0;
|
||||
if (siginfo_static.signal_received)
|
||||
|
||||
if (ws->mode == WSO_MODE_SERVICE)
|
||||
{
|
||||
ret = siginfo_static.signal_received;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ws->mode == WSO_MODE_SERVICE)
|
||||
if (win32_service_interrupt(ws))
|
||||
{
|
||||
if (win32_service_interrupt(ws))
|
||||
{
|
||||
ret = SIGTERM;
|
||||
}
|
||||
}
|
||||
else if (ws->mode == WSO_MODE_CONSOLE)
|
||||
{
|
||||
switch (win32_keyboard_get(ws))
|
||||
{
|
||||
case 0x3B: /* F1 -> USR1 */
|
||||
ret = SIGUSR1;
|
||||
break;
|
||||
|
||||
case 0x3C: /* F2 -> USR2 */
|
||||
ret = SIGUSR2;
|
||||
break;
|
||||
|
||||
case 0x3D: /* F3 -> HUP */
|
||||
ret = SIGHUP;
|
||||
break;
|
||||
|
||||
case 0x3E: /* F4 -> TERM */
|
||||
ret = SIGTERM;
|
||||
}
|
||||
}
|
||||
else if (ws->mode == WSO_MODE_CONSOLE)
|
||||
{
|
||||
switch (win32_keyboard_get(ws))
|
||||
{
|
||||
case 0x3B: /* F1 -> USR1 */
|
||||
ret = SIGUSR1;
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x3C: /* F2 -> USR2 */
|
||||
ret = SIGUSR2;
|
||||
break;
|
||||
|
||||
case 0x3D: /* F3 -> HUP */
|
||||
ret = SIGHUP;
|
||||
break;
|
||||
|
||||
case 0x3E: /* F4 -> TERM */
|
||||
ret = SIGTERM;
|
||||
break;
|
||||
|
||||
case 0x03: /* CTRL-C -> TERM */
|
||||
ret = SIGTERM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
throw_signal(ret); /* this will update signinfo_static.signal received */
|
||||
case 0x03: /* CTRL-C -> TERM */
|
||||
ret = SIGTERM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
if (ret)
|
||||
{
|
||||
throw_signal(ret); /* this will update signinfo_static.signal received */
|
||||
}
|
||||
return (siginfo_static.signal_received);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1603,4 +1597,47 @@ set_openssl_env_vars()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
win32_sleep(const int n)
|
||||
{
|
||||
if (n < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sleep() is not interruptible. Use a WAIT_OBJECT to catch signal */
|
||||
|
||||
if (!HANDLE_DEFINED(win32_signal.in.read))
|
||||
{
|
||||
if (n > 0)
|
||||
{
|
||||
Sleep(n*1000);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
update_time();
|
||||
time_t expire = now + n;
|
||||
|
||||
while (expire >= now)
|
||||
{
|
||||
DWORD status = WaitForSingleObject(win32_signal.in.read, (expire-now)*1000);
|
||||
if ((status == WAIT_OBJECT_0 && win32_signal_get(&win32_signal))
|
||||
|| status == WAIT_TIMEOUT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
update_time();
|
||||
|
||||
if (status != WAIT_OBJECT_0) /* wait failed or some unexpected error ? */
|
||||
{
|
||||
if (expire > now)
|
||||
{
|
||||
Sleep((expire-now)*1000);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ifdef _WIN32 */
|
||||
|
|
|
|||
|
|
@ -330,5 +330,8 @@ openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned in
|
|||
bool
|
||||
openvpn_swprintf(wchar_t *const str, const size_t size, const wchar_t *const format, ...);
|
||||
|
||||
/* Sleep that can be interrupted by signals and exit event */
|
||||
void win32_sleep(const int n);
|
||||
|
||||
#endif /* ifndef OPENVPN_WIN32_H */
|
||||
#endif /* ifdef _WIN32 */
|
||||
|
|
|
|||
Loading…
Reference in a new issue