X-Git-Url: http://git.archive.openwrt.org/?p=project%2Flibubox.git;a=blobdiff_plain;f=uloop.c;h=9a77ce49a5a7c2444a768eac3eb5059f52681fb3;hp=54ebe8d7b0ab05c7e1724ea3d05b1512f0ff9b6b;hb=d133da5562b36d5ac871cbe927bb9ecdf0569a51;hpb=b9ebdbcc648274cc630b6349374f9fb21e53f396 diff --git a/uloop.c b/uloop.c index 54ebe8d..9a77ce4 100644 --- a/uloop.c +++ b/uloop.c @@ -58,7 +58,6 @@ static struct list_head processes = LIST_HEAD_INIT(processes); static int poll_fd = -1; bool uloop_cancelled = false; -bool uloop_handle_sigchld = true; static bool do_sigchld = false; static struct uloop_fd_event cur_fds[ULOOP_MAX_EVENTS]; @@ -174,7 +173,8 @@ static int uloop_fetch_events(int timeout) if (events[n].flags & EV_ERROR) { u->error = true; - uloop_fd_delete(u); + if (!(u->flags & ULOOP_ERROR_CB)) + uloop_fd_delete(u); } if(events[n].filter == EVFILT_READ) @@ -268,7 +268,8 @@ static int uloop_fetch_events(int timeout) if (events[n].events & (EPOLLERR|EPOLLHUP)) { u->error = true; - uloop_fd_delete(u); + if (!(u->flags & ULOOP_ERROR_CB)) + uloop_fd_delete(u); } if(!(events[n].events & (EPOLLRDHUP|EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP))) { @@ -383,6 +384,7 @@ int uloop_fd_add(struct uloop_fd *sock, unsigned int flags) sock->registered = true; sock->eof = false; + sock->error = false; out: return ret; @@ -392,15 +394,16 @@ int uloop_fd_delete(struct uloop_fd *fd) { int i; - if (!fd->registered) - return 0; - for (i = 0; i < cur_nfds; i++) { if (cur_fds[cur_fd + i].fd != fd) continue; cur_fds[cur_fd + i].fd = NULL; } + + if (!fd->registered) + return 0; + fd->registered = false; uloop_fd_stack_event(fd, -1); return __uloop_fd_delete(fd); @@ -555,19 +558,37 @@ static void uloop_sigchld(int signo) do_sigchld = true; } -static void uloop_setup_signals(void) +static void uloop_install_handler(int signum, void (*handler)(int), struct sigaction* old, bool add) { struct sigaction s; + struct sigaction *act; - memset(&s, 0, sizeof(struct sigaction)); - s.sa_handler = uloop_handle_sigint; - s.sa_flags = 0; - sigaction(SIGINT, &s, NULL); + act = NULL; + sigaction(signum, NULL, &s); - if (uloop_handle_sigchld) { - s.sa_handler = uloop_sigchld; - sigaction(SIGCHLD, &s, NULL); + if (add) { + if (s.sa_handler == SIG_DFL) { /* Do not override existing custom signal handlers */ + memcpy(old, &s, sizeof(struct sigaction)); + s.sa_handler = handler; + s.sa_flags = 0; + act = &s; + } } + else if (s.sa_handler == handler) { /* Do not restore if someone modified our handler */ + act = old; + } + + if (act != NULL) + sigaction(signum, act, NULL); +} + +static void uloop_setup_signals(bool add) +{ + static struct sigaction old_sigint, old_sigchld, old_sigterm; + + uloop_install_handler(SIGINT, uloop_handle_sigint, &old_sigint, add); + uloop_install_handler(SIGTERM, uloop_handle_sigint, &old_sigterm, add); + uloop_install_handler(SIGCHLD, uloop_sigchld, &old_sigchld, add); } static int uloop_get_next_timeout(struct timeval *tv) @@ -620,9 +641,17 @@ static void uloop_clear_processes(void) void uloop_run(void) { + static int recursive_calls = 0; 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 (!recursive_calls++) + uloop_setup_signals(true); + + uloop_cancelled = false; while(!uloop_cancelled) { uloop_gettime(&tv); @@ -632,8 +661,12 @@ void uloop_run(void) if (do_sigchld) uloop_handle_processes(); + uloop_gettime(&tv); uloop_run_events(uloop_get_next_timeout(&tv)); } + + if (!--recursive_calls) + uloop_setup_signals(false); } void uloop_done(void)