From: Kristian Evensen <[email protected]> uloop_run calls uloop_setup_signals() to set up signal handling before the while loop, but does not remove the signal handling after the loop has ended. This can cause problems for for example applications using the ubus file descriptor in their own event loops, and perhaps with their own signal handling.
This patch stores the signal handle that was in place when the initial uloop_run() call was made, and restores the handle when this call returns. For recursive calls, the signal handler is not updated. One use-case I experienced was an application that subscribed to several ubus objects and used the ubus file descriptor in its own event loop. Even though ubus_register_subscriber() (which calls uloop_run()) had returned, the signal handler was not removed. This caused SIGINT not to be caught by the application. Signed-off-by: Kristian Evensen <[email protected]> --- uloop.c | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/uloop.c b/uloop.c index 9a0590f..7d11fc1 100644 --- a/uloop.c +++ b/uloop.c @@ -64,6 +64,13 @@ static bool do_sigchld = false; static struct uloop_fd_event cur_fds[ULOOP_MAX_EVENTS]; static int cur_fd, cur_nfds; +/** + * Used to store/restore the original signal handlers. I.e., the signal handlers + * that were in place beore the initial call to uloop_run(). + */ +static struct sigaction org_sighandler, org_sighandler_child; +static int uloop_recursive_count = 0; + #ifdef USE_KQUEUE int uloop_init(void) @@ -556,18 +563,36 @@ static void uloop_sigchld(int signo) do_sigchld = true; } -static void uloop_setup_signals(void) +static void uloop_setup_signals(bool add) { struct sigaction s; + struct sigaction *act, *oldact; memset(&s, 0, sizeof(struct sigaction)); - s.sa_handler = uloop_handle_sigint; - s.sa_flags = 0; - sigaction(SIGINT, &s, NULL); + + if (add) { + s.sa_handler = uloop_handle_sigint; + s.sa_flags = 0; + act = &s; + oldact = &org_sighandler; + } else { + act = &org_sighandler; + oldact = NULL; + } + + sigaction(SIGINT, act, oldact); if (uloop_handle_sigchld) { - s.sa_handler = uloop_sigchld; - sigaction(SIGCHLD, &s, NULL); + if (add) { + //act already points to s, so no need to update pointer + s.sa_handler = uloop_sigchld; + oldact = &org_sighandler_child; + } else { + act = &org_sighandler_child; + oldact = NULL; + } + + sigaction(SIGCHLD, act, oldact); } } @@ -623,7 +648,13 @@ void uloop_run(void) { struct timeval tv; - uloop_setup_signals(); + /* + * Handlers are only updated for the first call to uloop_run() (and restored + * when this call is done). + */ + if (!uloop_recursive_count++) + uloop_setup_signals(true); + while(!uloop_cancelled) { uloop_gettime(&tv); @@ -636,6 +667,9 @@ void uloop_run(void) uloop_gettime(&tv); uloop_run_events(uloop_get_next_timeout(&tv)); } + + if (!--uloop_recursive_count) + uloop_setup_signals(false); } void uloop_done(void) -- 1.8.3.2 _______________________________________________ openwrt-devel mailing list [email protected] https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
