X-Git-Url: https://git.decadent.org.uk/gitweb/?p=ion3.git;a=blobdiff_plain;f=libmainloop%2Fsignal.c;h=c5365532dd1b56d537d9150887df06a6b4385307;hp=37ee995f507da6818d8b0c622d9a9782ef12a0c4;hb=HEAD;hpb=214381793227e299ae1e72caa24ad2cfde029ef1 diff --git a/libmainloop/signal.c b/libmainloop/signal.c index 37ee995..c536553 100644 --- a/libmainloop/signal.c +++ b/libmainloop/signal.c @@ -1,7 +1,7 @@ /* * ion/libmainloop/signal.c * - * Copyright (c) Tuomo Valkonen 1999-2007. + * Copyright (c) Tuomo Valkonen 1999-2009. * * See the included file LICENSE for details. */ @@ -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_usecwhen.tv_usec+=USECS_IN_SEC; - queue->when.tv_sec--; + mainloop_gettime(tv); + if(TIMEVAL_LATER((queue)->when, (*tv))){ + if(queue->when.tv_usectv_usec){ + tv->tv_usec=(queue->when.tv_usec+USECS_IN_SEC)-tv->tv_usec; + /* TIMEVAL_LATER ensures >= 0 */ + tv->tv_sec=(queue->when.tv_sec-1)-tv->tv_sec; + }else{ + tv->tv_usec=queue->when.tv_usec-tv->tv_usec; + tv->tv_sec=queue->when.tv_sec-tv->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; /* 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); } } @@ -217,8 +226,10 @@ bool mainloop_check_signals() return kill_sig; /* Check for timer events in the queue */ - while(had_tmr && queue!=NULL){ + while(had_tmr){ had_tmr=FALSE; + if(queue==NULL) + break; mainloop_gettime(¤t_time); while(queue!=NULL){ if(TIMEVAL_LATER(current_time, queue->when)){ @@ -250,6 +261,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 +498,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 +510,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 +534,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){