From: Selva Nair Date: Sun, 1 Jan 2023 21:51:07 +0000 (-0500) Subject: Assign and honour signal priority order X-Git-Tag: v2.6_rc2~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b3b1436955b9db8e557fc58b7e37ba3a881109a6;p=thirdparty%2Fopenvpn.git Assign and honour signal priority order Signals are ordered as SIGUSR2, SIGUSR1, SIGHUP, SIGTERM, SIGINT in increasing priority. Lower priority signals are not allowed to overwrite higher ones. This should fix Trac #311, #639 -- SIGTER/SIGINT lost during dns resolution (except for the Windows-specific bug handled in previous commit). On sending SIGTERM during dns resolution, it still takes several seconds to terminate as the signal will get processed only after getaddrinfo times out twice (in phase1 and phase2 inits). Github: fixes OpenVPN/openvpn#205 Trac: #311, #639 Note: one has to still wait for address resolution to time out as getaddrinfo() is no interruptible. But a single ctrl-C (and some patience) is enough. Signed-off-by: Selva Nair Acked-by: Arne Schwabe Message-Id: <20230101215109.1521549-4-selva.nair@gmail.com> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg25871.html Signed-off-by: Gert Doering (cherry picked from commit 3a7257925791a086c1ac88362a8eb422be518b14) --- diff --git a/src/openvpn/proxy.c b/src/openvpn/proxy.c index 91121f250..120ba85e9 100644 --- a/src/openvpn/proxy.c +++ b/src/openvpn/proxy.c @@ -1080,10 +1080,7 @@ done: return ret; error: - if (!sig_info->signal_received) - { - register_signal(sig_info, SIGUSR1, "HTTP proxy error"); /* SOFT-SIGUSR1 -- HTTP proxy error */ - } + register_signal(sig_info, SIGUSR1, "HTTP proxy error"); /* SOFT-SIGUSR1 -- HTTP proxy error */ gc_free(&gc); return ret; } diff --git a/src/openvpn/sig.c b/src/openvpn/sig.c index e462b93e4..d6b18cb19 100644 --- a/src/openvpn/sig.c +++ b/src/openvpn/sig.c @@ -47,16 +47,17 @@ struct signal_info siginfo_static; /* GLOBAL */ struct signame { int value; + int priority; const char *upper; const char *lower; }; static const struct signame signames[] = { - { SIGINT, "SIGINT", "sigint"}, - { SIGTERM, "SIGTERM", "sigterm" }, - { SIGHUP, "SIGHUP", "sighup" }, - { SIGUSR1, "SIGUSR1", "sigusr1" }, - { SIGUSR2, "SIGUSR2", "sigusr2" } + { SIGINT, 5, "SIGINT", "sigint"}, + { SIGTERM, 4, "SIGTERM", "sigterm" }, + { SIGHUP, 3, "SIGHUP", "sighup" }, + { SIGUSR1, 2, "SIGUSR1", "sigusr1" }, + { SIGUSR2, 1, "SIGUSR2", "sigusr2" } }; int @@ -73,6 +74,19 @@ parse_signal(const char *signame) return -1; } +static int +signal_priority(int sig) +{ + for (size_t i = 0; i < SIZE(signames); ++i) + { + if (sig == signames[i].value) + { + return signames[i].priority; + } + } + return -1; +} + const char * signal_name(const int sig, const bool upper) { @@ -103,16 +117,22 @@ signal_description(const int signum, const char *sigtext) void throw_signal(const int signum) { - siginfo_static.signal_received = signum; - siginfo_static.source = SIG_SOURCE_HARD; + if (signal_priority(signum) >= signal_priority(siginfo_static.signal_received)) + { + siginfo_static.signal_received = signum; + siginfo_static.source = SIG_SOURCE_HARD; + } } void throw_signal_soft(const int signum, const char *signal_text) { - siginfo_static.signal_received = signum; - siginfo_static.source = SIG_SOURCE_SOFT; - siginfo_static.signal_text = signal_text; + if (signal_priority(signum) >= signal_priority(siginfo_static.signal_received)) + { + siginfo_static.signal_received = signum; + siginfo_static.source = SIG_SOURCE_SOFT; + siginfo_static.signal_text = signal_text; + } } void @@ -472,9 +492,10 @@ process_signal(struct context *c) void register_signal(struct signal_info *si, int sig, const char *text) { - if (si->signal_received != SIGTERM) + if (signal_priority(sig) >= signal_priority(si->signal_received)) { si->signal_received = sig; + si->signal_text = text; + si->source = SIG_SOURCE_SOFT; } - si->signal_text = text; } diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index 77c5c2ff8..bb3be4283 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -2277,8 +2277,12 @@ link_socket_init_phase2(struct context *c) done: if (sig_save.signal_received) { - /* This can potentially lose a saved high priority signal -- to be fixed */ - if (!sig_info->signal_received) + /* Always restore the saved signal -- register/throw_signal will handle priority */ + if (sig_save.source == SIG_SOURCE_HARD && sig_info == &siginfo_static) + { + throw_signal(sig_save.signal_received); + } + else { register_signal(sig_info, sig_save.signal_received, sig_save.signal_text); } diff --git a/src/openvpn/socks.c b/src/openvpn/socks.c index b2ca37441..8f2ae226c 100644 --- a/src/openvpn/socks.c +++ b/src/openvpn/socks.c @@ -499,11 +499,8 @@ establish_socks_proxy_passthru(struct socks_proxy_info *p, return; error: - if (!sig_info->signal_received) - { - /* SOFT-SIGUSR1 -- socks error */ - register_signal(sig_info, SIGUSR1, "socks-error"); - } + /* SOFT-SIGUSR1 -- socks error */ + register_signal(sig_info, SIGUSR1, "socks-error"); return; } @@ -543,11 +540,8 @@ establish_socks_proxy_udpassoc(struct socks_proxy_info *p, return; error: - if (!sig_info->signal_received) - { - /* SOFT-SIGUSR1 -- socks error */ - register_signal(sig_info, SIGUSR1, "socks-error"); - } + /* SOFT-SIGUSR1 -- socks error */ + register_signal(sig_info, SIGUSR1, "socks-error"); return; }