In order to make the mainloop a reusable library function, it should not take over any POSIX signals. Handle the signals in main.c instead, and use the cancel_fd mechanism to tell the mainloop to exit. Signed-off-by: Kevin Cernekee <cernekee at gmail.com> --- cstp.c | 2 +- libopenconnect.map.in | 1 + main.c | 33 +++++++++++++++++++++++++++++++-- mainloop.c | 28 ++++------------------------ openconnect-internal.h | 3 --- openconnect.h | 4 ++++ tun.c | 1 - 7 files changed, 41 insertions(+), 31 deletions(-) diff --git a/cstp.c b/cstp.c index bb79e7e..beab3f9 100644 --- a/cstp.c +++ b/cstp.c @@ -567,7 +567,7 @@ int cstp_reconnect(struct openconnect_info *vpninfo) _("sleep %ds, remaining timeout %ds\n"), interval, timeout); sleep(interval); - if (killed) + if (cancel_fd_check(vpninfo)) return 1; timeout -= interval; interval += vpninfo->reconnect_interval; diff --git a/libopenconnect.map.in b/libopenconnect.map.in index 2845754..a530324 100644 --- a/libopenconnect.map.in +++ b/libopenconnect.map.in @@ -46,6 +46,7 @@ OPENCONNECT_2.2 { OPENCONNECT_2.3 { global: openconnect_setup_cancel_pipe; + openconnect_mainloop; } OPENCONNECT_2.2; OPENCONNECT_PRIVATE { diff --git a/main.c b/main.c index 5ddd9b8..b3b1776 100644 --- a/main.c +++ b/main.c @@ -331,6 +331,20 @@ static void read_stdin(char **string) if (c) *c = 0; } + +static int sig_cancel_fd; +static int sig_caught; + +static void handle_sigint(int sig) +{ + char x = 'x'; + + sig_caught = sig; + if (write(sig_cancel_fd, &x, 1) < 0) { + /* suppress warn_unused_result */ + } +} + static void handle_sigusr(int sig) { if (sig == SIGUSR1) @@ -795,12 +809,23 @@ int main(int argc, char **argv) vpninfo->progress = syslog_progress; } + sig_cancel_fd = openconnect_setup_cancel_pipe(vpninfo); + if (sig_cancel_fd < 0) { + fprintf(stderr, _("Error opening cancel pipe\n")); + exit(1); + } + memset(&sa, 0, sizeof(sa)); - sa.sa_handler = handle_sigusr; + sa.sa_handler = handle_sigusr; sigaction(SIGUSR1, &sa, NULL); sigaction(SIGUSR2, &sa, NULL); + sa.sa_handler = handle_sigint; + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGHUP, &sa, NULL); + if (vpninfo->sslkey && do_passphrase_from_fsid) openconnect_passphrase_from_fsid(vpninfo); @@ -921,7 +946,11 @@ int main(int argc, char **argv) if (fp) fclose(fp); } - vpn_mainloop(vpninfo); + openconnect_mainloop(vpninfo); + + if (sig_caught) + vpn_progress(vpninfo, PRG_INFO, _("Caught signal: %s\n"), strsignal(sig_caught)); + if (fp) unlink(pidfile); exit(1); diff --git a/mainloop.c b/mainloop.c index 2d10147..ccd1861 100644 --- a/mainloop.c +++ b/mainloop.c @@ -27,7 +27,6 @@ #include <limits.h> #include <sys/select.h> #include <stdlib.h> -#include <signal.h> #include <unistd.h> #include <string.h> @@ -55,23 +54,9 @@ int queue_new_packet(struct pkt **q, void *buf, int len) return 0; } -int killed; - -static void handle_sigint(int sig) -{ - killed = sig; -} - -int vpn_mainloop(struct openconnect_info *vpninfo) +int openconnect_mainloop(struct openconnect_info *vpninfo) { - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = handle_sigint; - - sigaction(SIGTERM, &sa, NULL); - sigaction(SIGINT, &sa, NULL); - sigaction(SIGHUP, &sa, NULL); - + cancel_fd_set(vpninfo, &vpninfo->select_rfds, &vpninfo->select_nfds); while (!vpninfo->quit_reason) { int did_work = 0; int timeout = INT_MAX; @@ -103,13 +88,8 @@ int vpn_mainloop(struct openconnect_info *vpninfo) if (vpninfo->quit_reason) break; - if (killed) { - if (killed == SIGHUP) - vpninfo->quit_reason = "Client received SIGHUP"; - else if (killed == SIGINT) - vpninfo->quit_reason = "Client received SIGINT"; - else - vpninfo->quit_reason = "Client killed"; + if (cancel_fd_check(vpninfo)) { + vpninfo->quit_reason = "Aborted by caller"; break; } diff --git a/openconnect-internal.h b/openconnect-internal.h index 549448c..5215ea5 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -450,14 +450,11 @@ int openconnect_local_cert_md5(struct openconnect_info *vpninfo, /* mainloop.c */ int vpn_add_pollfd(struct openconnect_info *vpninfo, int fd, short events); -int vpn_mainloop(struct openconnect_info *vpninfo); int queue_new_packet(struct pkt **q, void *buf, int len); void queue_packet(struct pkt **q, struct pkt *new); int keepalive_action(struct keepalive_info *ka, int *timeout); int ka_stalled_action(struct keepalive_info *ka, int *timeout); -extern int killed; - /* xml.c */ int config_lookup_host(struct openconnect_info *vpninfo, const char *host); diff --git a/openconnect.h b/openconnect.h index 47ac8b5..6297e4a 100644 --- a/openconnect.h +++ b/openconnect.h @@ -224,6 +224,10 @@ int openconnect_setup_cancel_pipe(struct openconnect_info *vpninfo); const char *openconnect_get_version(void); +/* Start the main loop; exits if data is received on cancel_fd or the remote + site aborts. */ +int openconnect_mainloop(struct openconnect_info *vpninfo); + /* The first (privdata) argument to each of these functions is either the privdata argument provided to openconnect_vpninfo_new_with_cbdata(), or if that argument was NULL then it'll be the vpninfo itself. */ diff --git a/tun.c b/tun.c index 8f5f1b9..0db7c43 100644 --- a/tun.c +++ b/tun.c @@ -28,7 +28,6 @@ #include <sys/ioctl.h> #include <sys/wait.h> #include <string.h> -#include <signal.h> #include <fcntl.h> #include <unistd.h> #include <netdb.h> -- 1.7.9.5