]> git.ipfire.org Git - people/ms/dma.git/commitdiff
add SIGALRM/timeout infrastructure
authorSimon Schubert <2@0x2c.org>
Wed, 30 Jun 2010 22:00:03 +0000 (00:00 +0200)
committerSimon Schubert <2@0x2c.org>
Wed, 30 Jun 2010 22:39:24 +0000 (00:39 +0200)
dma.h
util.c

diff --git a/dma.h b/dma.h
index a35e671e9594a5bca516eef884551e75d904876b..2b5cd259aa22d0be47465203e4c5baf10b54b4f3 100644 (file)
--- a/dma.h
+++ b/dma.h
@@ -199,6 +199,7 @@ void errlog(int, const char *, ...);
 void errlogx(int, const char *, ...);
 void set_username(void);
 void deltmp(void);
+int do_timeout(int, int);
 int open_locked(const char *, int, ...);
 char *rfc822date(void);
 int strprefixcmp(const char *, const char *);
diff --git a/util.c b/util.c
index a43080858c775cde3b7287c4894ac5aaf6cc68ec..e25cdb5653c5855281f4a1a053ca390375824855 100644 (file)
--- a/util.c
+++ b/util.c
@@ -39,6 +39,8 @@
 #include <fcntl.h>
 #include <netdb.h>
 #include <pwd.h>
+#include <setjmp.h>
+#include <signal.h>
 #include <stdio.h>
 #include <syslog.h>
 #include <unistd.h>
@@ -211,6 +213,52 @@ deltmp(void)
        }
 }
 
+static sigjmp_buf sigbuf;
+static int sigbuf_valid;
+
+static void
+sigalrm_handler(int signo)
+{
+       (void)signo;    /* so that gcc doesn't complain */
+       if (sigbuf_valid)
+               siglongjmp(sigbuf, 1);
+}
+
+int
+do_timeout(int timeout, int dojmp)
+{
+       struct sigaction act;
+       int ret = 0;
+
+       sigemptyset(&act.sa_mask);
+       act.sa_flags = 0;
+
+       if (timeout) {
+               act.sa_handler = sigalrm_handler;
+               if (sigaction(SIGALRM, &act, NULL) != 0)
+                       syslog(LOG_WARNING, "can not set signal handler: %m");
+               if (dojmp) {
+                       ret = sigsetjmp(sigbuf, 1);
+                       if (ret)
+                               goto disable;
+                       /* else just programmed */
+                       sigbuf_valid = 1;
+               }
+
+               alarm(timeout);
+       } else {
+disable:
+               alarm(0);
+
+               act.sa_handler = SIG_IGN;
+               if (sigaction(SIGALRM, &act, NULL) != 0)
+                       syslog(LOG_WARNING, "can not remove signal handler: %m");
+               sigbuf_valid = 0;
+       }
+
+       return (ret);
+}
+
 int
 open_locked(const char *fname, int flags, ...)
 {