X-Git-Url: http://git.archive.openwrt.org/?p=project%2Flibubox.git;a=blobdiff_plain;f=uloop.c;h=1c5bcee73a12c07c664ea5eb1d41fd427afa049f;hp=af84737c28ce6112337ee2362e23444885d7c57f;hb=f9db1cb918da64101fdc72422551d95b054b1a38;hpb=93be9309b86d07eaa3b83ad07d380ca3092b29a1 diff --git a/uloop.c b/uloop.c index af84737..1c5bcee 100644 --- a/uloop.c +++ b/uloop.c @@ -56,15 +56,15 @@ static struct uloop_fd_stack *fd_stack = NULL; static struct list_head timeouts = LIST_HEAD_INIT(timeouts); static struct list_head processes = LIST_HEAD_INIT(processes); -static int signal_fd = -1; static int poll_fd = -1; bool uloop_cancelled = false; +static int uloop_status = 0; static bool do_sigchld = false; static struct uloop_fd_event cur_fds[ULOOP_MAX_EVENTS]; static int cur_fd, cur_nfds; -static void uloop_handle_signal(int signo); +int uloop_fd_add(struct uloop_fd *sock, unsigned int flags); #ifdef USE_KQUEUE #include "uloop-kqueue.c" @@ -74,6 +74,60 @@ static void uloop_handle_signal(int signo); #include "uloop-epoll.c" #endif +static void waker_consume(struct uloop_fd *fd, unsigned int events) +{ + char buf[4]; + + while (read(fd->fd, buf, 4) > 0) + ; +} + +static int waker_pipe = -1; +static struct uloop_fd waker_fd = { + .fd = -1, + .cb = waker_consume, +}; + +static void waker_init_fd(int fd) +{ + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); +} + +static int waker_init(void) +{ + int fds[2]; + + if (waker_pipe >= 0) + return 0; + + if (pipe(fds) < 0) + return -1; + + waker_init_fd(fds[0]); + waker_init_fd(fds[1]); + waker_pipe = fds[1]; + + waker_fd.fd = fds[0]; + waker_fd.cb = waker_consume; + uloop_fd_add(&waker_fd, ULOOP_READ); + + return 0; +} + +int uloop_init(void) +{ + if (uloop_init_pollfd() < 0) + return -1; + + if (waker_init() < 0) { + uloop_done(); + return -1; + } + + return 0; +} + static bool uloop_fd_stack_event(struct uloop_fd *fd, int events) { struct uloop_fd_stack *cur; @@ -331,17 +385,28 @@ static void uloop_handle_processes(void) } -static void uloop_handle_signal(int signo) +static void uloop_signal_wake(void) { - switch (signo) { - case SIGINT: - case SIGQUIT: - case SIGTERM: - uloop_cancelled = true; + do { + if (write(waker_pipe, "w", 1) < 0) { + if (errno == EINTR) + continue; + } break; - case SIGCHLD: - do_sigchld = true; - } + } while (1); +} + +static void uloop_handle_sigint(int signo) +{ + uloop_status = signo; + uloop_cancelled = true; + uloop_signal_wake(); +} + +static void uloop_sigchld(int signo) +{ + do_sigchld = true; + uloop_signal_wake(); } static void uloop_install_handler(int signum, void (*handler)(int), struct sigaction* old, bool add) @@ -392,14 +457,11 @@ static void uloop_ignore_signal(int signum, bool ignore) static void uloop_setup_signals(bool add) { - static struct sigaction old_sigint, old_sigchld, old_sigterm, old_sigquit; + static struct sigaction old_sigint, old_sigchld, old_sigterm; - uloop_setup_signalfd(add); - - uloop_install_handler(SIGINT, uloop_handle_signal, &old_sigint, add); - uloop_install_handler(SIGTERM, uloop_handle_signal, &old_sigterm, add); - uloop_install_handler(SIGQUIT, uloop_handle_signal, &old_sigquit, add); - uloop_install_handler(SIGCHLD, uloop_handle_signal, &old_sigchld, add); + 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); uloop_ignore_signal(SIGPIPE, add); } @@ -452,7 +514,7 @@ static void uloop_clear_processes(void) uloop_process_delete(p); } -void uloop_run(void) +int uloop_run(void) { static int recursive_calls = 0; struct timeval tv; @@ -464,8 +526,9 @@ void uloop_run(void) if (!recursive_calls++) uloop_setup_signals(true); + uloop_status = 0; uloop_cancelled = false; - while(!uloop_cancelled) + while (!uloop_cancelled) { uloop_gettime(&tv); uloop_process_timeouts(&tv); @@ -482,20 +545,23 @@ void uloop_run(void) if (!--recursive_calls) uloop_setup_signals(false); + + return uloop_status; } void uloop_done(void) { - if (signal_fd >= 0) { - close(signal_fd); - signal_fd = -1; + if (poll_fd >= 0) { + close(poll_fd); + poll_fd = -1; } - if (poll_fd < 0) - return; - - close(poll_fd); - poll_fd = -1; + if (waker_pipe >= 0) { + uloop_fd_delete(&waker_fd); + close(waker_pipe); + close(waker_fd.fd); + waker_pipe = -1; + } uloop_clear_timeouts(); uloop_clear_processes();