Hello,
The following patch is an attempt to manage signals in pppob in a more robust way, it uses signalfd. * the signal interception is move into main, before the thread creation so that signal mask is shared between threads
* a signalfd is created and appended to the fd set monitored by select.

The main advantage I see is that it allows to get rid of timeouts.

The main drawback I see is that signalfd is linux specific, hence breaking compatibility with other unices. To solve this issue, one could simulate a signalfd with a pipe. I didn't had the time to do it, for now.

Any comment or suggestion is welcome.

Regards,

--
Nicolas CARRIER - Parrot France

--- barry-0.17.1git/tools/pppob.cc	2011-06-06 10:48:48.000000000 +0200
+++ /home/ncarrier/workspace/barry/tools/pppob.cc	2011-06-10 09:36:40.704972589 +0200
@@ -31,6 +31,7 @@
 #include <sys/select.h>
 #include <sys/time.h>
 #include <sys/types.h>
+#include <sys/signalfd.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <signal.h>
@@ -91,26 +92,36 @@
 	Data data;
 	int bytes_read;
 	fd_set rfds;
-	struct timeval tv;
+	int sfd;
 	int ret;
 
-	// Handle interrupt signals from pppd
+	// Handle interrupt signals
+	sigset_t mask;
+
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGTERM);
+	sigaddset(&mask, SIGINT);
+	sigaddset(&mask, SIGHUP);
+
 	signal_end = false;
-	signal(SIGINT, &signal_handler);
-	signal(SIGHUP, &signal_handler);
-	signal(SIGTERM, &signal_handler);
+
+	sfd = signalfd (-1, &mask, 0);
+	if (sfd < 0) {
+		perror("signalfd");
+		return;
+	}
 
 	FD_ZERO(&rfds);
+
 	while( signal_end == false ) {
 		// Need to use select() here, so that pppd doesn't
 		// hang when it tries to set the line discipline
 		// on our stdin.
 
 		FD_SET(0, &rfds);
-		tv.tv_sec = 30;
-		tv.tv_usec = 0;
+		FD_SET(sfd, &rfds);
 
-		ret = select(1, &rfds, NULL, NULL, &tv);
+		ret = select(sfd + 1, &rfds, NULL, NULL, NULL);
 		if( ret == -1 ) {
 			perror("select()");
 		}
@@ -124,7 +135,34 @@
 				modem.Write(data);
 			}
 		}
+		else if( ret && FD_ISSET(sfd, &rfds) ) {
+			cout << "Killed by a signal, attempting to exit gracefully" << endl;
+			signal_end = true;
+		}
 	}
+
+	close(sfd);
+}
+
+/**
+ * Blocks signals that we handle ourselves
+ * @return non-zero on errors
+ */
+static int intercept_signals()
+{
+	sigset_t mask;
+
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGTERM);
+	sigaddset(&mask, SIGINT);
+	sigaddset(&mask, SIGHUP);
+
+	if (pthread_sigmask(SIG_BLOCK, &mask, NULL) < 0) {
+		perror ("pthread_sigmask");
+		return 1;
+	}
+
+	return 0;
 }
 
 int main(int argc, char *argv[])
@@ -134,6 +172,11 @@
 	cout.sync_with_stdio(true);	// leave this on, since libusb uses
 					// stdio for debug messages
 
+	if (intercept_signals() != 0) {
+		cerr << "Signal management failed" << endl;
+		return 1;
+	}
+
 	try {
 
 		uint32_t pin = 0;
------------------------------------------------------------------------------
EditLive Enterprise is the world's most technically advanced content
authoring tool. Experience the power of Track Changes, Inline Image
Editing and ensure content is compliant with Accessibility Checking.
http://p.sf.net/sfu/ephox-dev2dev
_______________________________________________
Barry-devel mailing list
Barry-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/barry-devel

Reply via email to