From 6f329fd6404650011ce8124a9c504e880ecc5a6b Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Mon, 14 Nov 2005 20:06:49 +0000 Subject: [PATCH] Changed main_loop shutdown logic once again. The former mechanism with a single global main_shutdown variable was too inflexible. I have given all hooks a possibility to either invoke an immediate shutdown or a "soft" shutdown which is activated if all hooks agree on it (the idea is that different parts of a single program can have their local opinion on whether there is more to do or not). --- lib/mainloop.c | 31 +++++++++++++++---------------- lib/mainloop.h | 11 +++++++++-- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/lib/mainloop.c b/lib/mainloop.c index 544a7b7d..5b5fb45a 100644 --- a/lib/mainloop.c +++ b/lib/mainloop.c @@ -345,7 +345,7 @@ main_rebuild_poll_table(void) main_poll_table_obsolete = 0; } -int +void main_loop(void) { DBG("MAIN: Entering main_loop"); @@ -366,12 +366,24 @@ main_loop(void) DBG("MAIN: Timer %p expired at %Ld", tm, (long long) 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,19 +407,6 @@ main_loop(void) wake = 0; } } - if (clist_empty(&main_file_list) && - clist_empty(&main_timer_list) && - clist_empty(&main_hook_list) && - clist_empty(&main_process_list)) - { - DBG("MAIN: Nothing to do, exiting"); - return 0; - } - if (main_shutdown) - { - DBG("MAIN: Shutdown"); - return 1; - } /* 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; diff --git a/lib/mainloop.h b/lib/mainloop.h index a8626f03..f321c2b5 100644 --- a/lib/mainloop.h +++ b/lib/mainloop.h @@ -71,10 +71,17 @@ void file_close_all(void); /* Close all known main_file's; frequently used bef struct main_hook { cnode n; - int (*handler)(struct main_hook *ho); /* [*] Hook function; returns 1 if should be called again */ + int (*handler)(struct main_hook *ho); /* [*] Hook function; returns HOOK_xxx */ void *data; /* [*] For use by the handler */ }; +enum main_hook_return { + HOOK_IDLE, /* Call again when the main loop becomes idle again */ + HOOK_RETRY, /* Call again as soon as possible */ + HOOK_DONE = -1, /* Shut down the main loop if all hooks return this value */ + HOOK_SHUTDOWN = -2 /* Shut down the main loop immediately */ +}; + void hook_add(struct main_hook *ho); void hook_del(struct main_hook *ho); @@ -96,7 +103,7 @@ int process_fork(struct main_process *mp); /* The main loop */ void main_init(void); -int main_loop(void); +void main_loop(void); void main_debug(void); #endif -- 2.39.2