/*
* ion/libmainloop/signal.c
*
- * Copyright (c) Tuomo Valkonen 1999-2007.
+ * Copyright (c) Tuomo Valkonen 1999-2009.
*
* See the included file LICENSE for details.
*/
WHook *mainloop_sigchld_hook=NULL;
WHook *mainloop_sigusr2_hook=NULL;
+static sigset_t special_sigs;
+
/*{{{ Timers */
#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){
- queue->when.tv_usec+=USECS_IN_SEC;
- queue->when.tv_sec--;
+ mainloop_gettime(tv);
+ if(TIMEVAL_LATER((queue)->when, (*tv))){
+ if(queue->when.tv_usec<tv->tv_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);
}
}
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)){
}
+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;
#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;
which=&dummy;
}
+ sigemptyset(&special_sigs);
sigemptyset(&set);
sigemptyset(&oldset);
sigprocmask(SIG_SETMASK, &set, &oldset);
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){