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