X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Fmainloop.c;h=affc4aec8efa0845ca67b20b01816464a2125cec;hb=ddef04ebd6ba9d2fde15fcd8fce37daf73775fea;hp=57e73742134e8d88e28b8dafba42c3becb2f360e;hpb=2f88183327a435c1cfd16e1e84673059a09b19ba;p=libucw.git diff --git a/lib/mainloop.c b/lib/mainloop.c index 57e73742..affc4aec 100644 --- a/lib/mainloop.c +++ b/lib/mainloop.c @@ -1,7 +1,7 @@ /* * UCW Library -- Main Loop * - * (c) 2004--2005 Martin Mares + * (c) 2004--2006 Martin Mares * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. @@ -14,7 +14,6 @@ #include #include -#include #include #include #include @@ -34,14 +33,14 @@ static uns main_poll_table_obsolete, main_poll_table_size; static struct pollfd *main_poll_table; static uns main_sigchld_set_up; -static void +void main_get_time(void) { struct timeval tv; gettimeofday(&tv, NULL); main_now_seconds = tv.tv_sec; main_now = (timestamp_t)tv.tv_sec * 1000 + tv.tv_usec / 1000; - DBG("It's %Ld o'clock", (long long) main_now); + // DBG("It's %Ld o'clock", (long long) main_now); } void @@ -52,12 +51,18 @@ main_init(void) clist_init(&main_file_list); clist_init(&main_hook_list); clist_init(&main_process_list); + main_file_cnt = 0; + main_poll_table_obsolete = 1; main_get_time(); } void timer_add(struct main_timer *tm, timestamp_t expires) { + if (expires) + DBG("MAIN: Setting timer %p (expire at now+%Ld)", tm, (long long)(expires-main_now)); + else + DBG("MAIN: Clearing timer %p", tm); if (tm->expires) clist_remove(&tm->n); tm->expires = expires; @@ -88,6 +93,7 @@ file_timer_expired(struct main_timer *tm) void file_add(struct main_file *fi) { + DBG("MAIN: Adding file %p (fd=%d)", fi, fi->fd); ASSERT(!fi->n.next); clist_add_tail(&main_file_list, &fi->n); fi->timer.handler = file_timer_expired; @@ -115,6 +121,7 @@ file_chg(struct main_file *fi) void file_del(struct main_file *fi) { + DBG("MAIN: Deleting file %p (fd=%d)", fi, fi->fd); ASSERT(fi->n.next); timer_del(&fi->timer); clist_remove(&fi->n); @@ -226,6 +233,7 @@ file_close_all(void) void hook_add(struct main_hook *ho) { + DBG("MAIN: Adding hook %p", ho); ASSERT(!ho->n.next); clist_add_tail(&main_hook_list, &ho->n); } @@ -233,6 +241,7 @@ hook_add(struct main_hook *ho) void hook_del(struct main_hook *ho) { + DBG("MAIN: Deleting hook %p", ho); ASSERT(ho->n.next); clist_remove(&ho->n); ho->n.next = ho->n.prev = NULL; @@ -247,6 +256,7 @@ main_sigchld_handler(int x UNUSED) void process_add(struct main_process *mp) { + DBG("MAIN: Adding process %p (pid=%d)", mp, mp->pid); ASSERT(!mp->n.next); ASSERT(mp->handler); clist_add_tail(&main_process_list, &mp->n); @@ -264,16 +274,15 @@ process_add(struct main_process *mp) void process_del(struct main_process *mp) { + DBG("MAIN: Deleting process %p (pid=%d)", mp, mp->pid); ASSERT(mp->n.next); clist_remove(&mp->n); - mp->pid = 0; mp->n.next = NULL; } int process_fork(struct main_process *mp) { - ASSERT(!mp->pid); pid_t pid = fork(); if (pid < 0) { @@ -335,7 +344,7 @@ main_rebuild_poll_table(void) main_poll_table = xmalloc(sizeof(struct pollfd) * main_poll_table_size); } struct pollfd *p = main_poll_table; - DBG("MAIN: Rebuliding poll table: %d of %d entries set", main_file_cnt, main_poll_table_size); + DBG("MAIN: Rebuilding poll table: %d of %d entries set", main_file_cnt, main_poll_table_size); CLIST_WALK(fi, main_file_list) { p->fd = fi->fd; @@ -357,21 +366,33 @@ main_loop(void) struct main_process *pr; cnode *tmp; - while (!main_shutdown) + for (;;) { main_get_time(); timestamp_t wake = main_now + 1000000000; while ((tm = clist_head(&main_timer_list)) && tm->expires <= main_now) { - DBG("MAIN: Timer %p expired at %Ld", tm, (long long) tm->expires); + DBG("MAIN: Timer %p expired at now-%Ld", tm, (long long)(main_now - tm->expires)); tm->handler(tm); } + int hook_min = HOOK_RETRY; + int hook_max = HOOK_SHUTDOWN; CLIST_WALK_DELSAFE(ho, main_hook_list, tmp) { DBG("MAIN: Hook %p", ho); - if (ho->handler(ho)) - wake = 0; + int ret = ho->handler(ho); + hook_min = MIN(hook_min, ret); + hook_max = MAX(hook_max, ret); + } + if (hook_min == HOOK_SHUTDOWN || + hook_min == HOOK_DONE && hook_max == HOOK_DONE || + main_shutdown) + { + DBG("MAIN: Shut down by %s", main_shutdown ? "main_shutdown" : "a hook"); + return; } + if (hook_max == HOOK_RETRY) + wake = 0; if (main_poll_table_obsolete) main_rebuild_poll_table(); if (!clist_empty(&main_process_list)) @@ -395,8 +416,6 @@ main_loop(void) wake = 0; } } - if (main_shutdown) - break; /* FIXME: Here is a small race window where SIGCHLD can come unnoticed. */ if ((tm = clist_head(&main_timer_list)) && tm->expires < wake) wake = tm->expires;