]> git.decadent.org.uk Git - ion3.git/blobdiff - libmainloop/signal.c
[svn-upgrade] Integrating new upstream version, ion3 (20080707)
[ion3.git] / libmainloop / signal.c
index 877e3ec808665b5a5b7a44a8d928eafb5ebfcae7..fd37161b332689c7073b5065f930ab5e11549428 100644 (file)
@@ -36,6 +36,8 @@ static bool had_tmr=FALSE;
 WHook *mainloop_sigchld_hook=NULL;
 WHook *mainloop_sigusr2_hook=NULL;
 
+static sigset_t special_sigs;
+
 
 /*{{{ Timers */
 
@@ -79,44 +81,51 @@ int mainloop_gettime(struct timeval *val)
 #define USECS_IN_SEC 1000000
 
 
-static void do_timer_set()
+bool libmainloop_get_timeout(struct timeval *tv)
 {
-    struct itimerval val={{0, 0}, {0, 0}};
-    
-    if(queue==NULL){
-        setitimer(ITIMER_REAL, &val, NULL);
-        return;
-    }
+    if(queue==NULL)
+        return FALSE;
 
     /* Subtract queue time from current time, don't go below zero */
-    mainloop_gettime(&(val.it_value));
-    if(TIMEVAL_LATER((queue)->when, val.it_value)){
-        if(queue->when.tv_usec<val.it_value.tv_usec){
+    mainloop_gettime(tv);
+    if(TIMEVAL_LATER((queue)->when, (*tv))){
+        if(queue->when.tv_usec<tv->tv_usec){
             queue->when.tv_usec+=USECS_IN_SEC;
             queue->when.tv_sec--;
         }
-        val.it_value.tv_usec=queue->when.tv_usec-val.it_value.tv_usec;
-        val.it_value.tv_sec=queue->when.tv_sec-val.it_value.tv_sec;
-        if(val.it_value.tv_usec<0)
-            val.it_value.tv_usec=0;
+        tv->tv_usec=queue->when.tv_usec-tv->tv_usec;
+        tv->tv_sec=queue->when.tv_sec-tv->tv_sec;
+        if(tv->tv_usec<0)
+            tv->tv_usec=0;
         /* POSIX and some kernels have been designed by absolute morons and 
          * contain idiotic artificial restrictions on the value of tv_usec, 
          * that will only cause more code being run and clock cycles being 
          * spent to do the same thing, as the kernel will in any case convert
          * the seconds to some other units.
          */
-         val.it_value.tv_sec+=val.it_value.tv_usec/USECS_IN_SEC;
-         val.it_value.tv_usec%=USECS_IN_SEC;
+         tv->tv_sec+=tv->tv_usec/USECS_IN_SEC;
+         tv->tv_usec%=USECS_IN_SEC;
     }else{
         had_tmr=TRUE;
-        return;
+        return FALSE;
     }
+    
+    return TRUE;
+}
+
 
-    val.it_interval.tv_usec=val.it_value.tv_usec;
-    val.it_interval.tv_sec=val.it_value.tv_sec;
+static void do_timer_set()
+{
+    struct itimerval val={{0, 0}, {0, 0}};
     
-    if((setitimer(ITIMER_REAL, &val, NULL))){
-        had_tmr=TRUE;
+    if(libmainloop_get_timeout(&val.it_value)){
+        val.it_interval.tv_usec=0;
+        val.it_interval.tv_sec=0;
+        
+        if((setitimer(ITIMER_REAL, &val, NULL)))
+            had_tmr=TRUE;
+    }else if(!had_tmr){
+        setitimer(ITIMER_REAL, &val, NULL);
     }
 }
 
@@ -250,6 +259,18 @@ bool mainloop_check_signals()
 }
 
 
+void mainloop_block_signals(sigset_t *oldmask)
+{
+    sigprocmask(SIG_BLOCK, &special_sigs, oldmask);
+}
+
+
+bool mainloop_unhandled_signals()
+{
+    return (usr2_sig || wait_sig || kill_sig || had_tmr);
+}
+
+
 static void add_to_current_time(struct timeval *when, uint msecs)
 {
     long tmp_usec;
@@ -475,6 +496,7 @@ static void ignore_handler(int signal_num)
 #define FATAL(X) IFTRAP(X) signal(X, fatal_signal_handler);
 #define IGNORE(X) IFTRAP(X) signal(X, SIG_IGN)
 
+
 void mainloop_trap_signals(const sigset_t *which)
 {
     struct sigaction sa;
@@ -486,6 +508,7 @@ void mainloop_trap_signals(const sigset_t *which)
         which=&dummy;
     }
     
+    sigemptyset(&special_sigs);
     sigemptyset(&set);
     sigemptyset(&oldset);
     sigprocmask(SIG_SETMASK, &set, &oldset);
@@ -509,24 +532,28 @@ void mainloop_trap_signals(const sigset_t *which)
         sa.sa_handler=timer_handler;
         sa.sa_flags=SA_RESTART;
         sigaction(SIGALRM, &sa, NULL);
+        sigaddset(&special_sigs, SIGALRM);
     }
 
     IFTRAP(SIGCHLD){
         sa.sa_handler=chld_handler;
         sa.sa_flags=SA_NOCLDSTOP|SA_RESTART;
         sigaction(SIGCHLD, &sa, NULL);
+        sigaddset(&special_sigs, SIGCHLD);
     }
 
     IFTRAP(SIGUSR2){
         sa.sa_handler=usr2_handler;
         sa.sa_flags=SA_RESTART;
         sigaction(SIGUSR2, &sa, NULL);
+        sigaddset(&special_sigs, SIGUSR2);
     }
 
     IFTRAP(SIGTERM){
         sa.sa_handler=exit_handler;
         sa.sa_flags=SA_RESTART;
         sigaction(SIGTERM, &sa, NULL);
+        sigaddset(&special_sigs, SIGTERM);
     }
     
     IFTRAP(SIGUSR1){