[PATCH/RFC V2 05/26] Convert vpn_mainloop() into a library function

Kevin Cernekee cernekee at gmail.com
Sun Aug 11 21:49:06 EDT 2013


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




More information about the openconnect-devel mailing list