X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=uloop.c;h=af84737c28ce6112337ee2362e23444885d7c57f;hb=93be9309b86d07eaa3b83ad07d380ca3092b29a1;hp=f2eb50a64a32a835e83210a35110311ad46eb89f;hpb=4b0aa9ccc22eff62e177b9777152e7937273b418;p=project%2Flibubox.git diff --git a/uloop.c b/uloop.c index f2eb50a..af84737 100644 --- a/uloop.c +++ b/uloop.c @@ -56,6 +56,7 @@ 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 bool do_sigchld = false; @@ -63,103 +64,14 @@ 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); + #ifdef USE_KQUEUE #include "uloop-kqueue.c" #endif #ifdef USE_EPOLL - -/** - * FIXME: uClibc < 0.9.30.3 does not define EPOLLRDHUP for Linux >= 2.6.17 - */ -#ifndef EPOLLRDHUP -#define EPOLLRDHUP 0x2000 -#endif - -int uloop_init(void) -{ - if (poll_fd >= 0) - return 0; - - poll_fd = epoll_create(32); - if (poll_fd < 0) - return -1; - - fcntl(poll_fd, F_SETFD, fcntl(poll_fd, F_GETFD) | FD_CLOEXEC); - return 0; -} - -static int register_poll(struct uloop_fd *fd, unsigned int flags) -{ - struct epoll_event ev; - int op = fd->registered ? EPOLL_CTL_MOD : EPOLL_CTL_ADD; - - memset(&ev, 0, sizeof(struct epoll_event)); - - if (flags & ULOOP_READ) - ev.events |= EPOLLIN | EPOLLRDHUP; - - if (flags & ULOOP_WRITE) - ev.events |= EPOLLOUT; - - if (flags & ULOOP_EDGE_TRIGGER) - ev.events |= EPOLLET; - - ev.data.fd = fd->fd; - ev.data.ptr = fd; - fd->flags = flags; - - return epoll_ctl(poll_fd, op, fd->fd, &ev); -} - -static struct epoll_event events[ULOOP_MAX_EVENTS]; - -static int __uloop_fd_delete(struct uloop_fd *sock) -{ - sock->flags = 0; - return epoll_ctl(poll_fd, EPOLL_CTL_DEL, sock->fd, 0); -} - -static int uloop_fetch_events(int timeout) -{ - int n, nfds; - - nfds = epoll_wait(poll_fd, events, ARRAY_SIZE(events), timeout); - for (n = 0; n < nfds; ++n) { - struct uloop_fd_event *cur = &cur_fds[n]; - struct uloop_fd *u = events[n].data.ptr; - unsigned int ev = 0; - - cur->fd = u; - if (!u) - continue; - - if (events[n].events & (EPOLLERR|EPOLLHUP)) { - u->error = true; - if (!(u->flags & ULOOP_ERROR_CB)) - uloop_fd_delete(u); - } - - if(!(events[n].events & (EPOLLRDHUP|EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP))) { - cur->fd = NULL; - continue; - } - - if(events[n].events & EPOLLRDHUP) - u->eof = true; - - if(events[n].events & EPOLLIN) - ev |= ULOOP_READ; - - if(events[n].events & EPOLLOUT) - ev |= ULOOP_WRITE; - - cur->events = ev; - } - - return nfds; -} - +#include "uloop-epoll.c" #endif static bool uloop_fd_stack_event(struct uloop_fd *fd, int events) @@ -399,6 +311,9 @@ static void uloop_handle_processes(void) while (1) { pid = waitpid(-1, &ret, WNOHANG); + if (pid < 0 && errno == EINTR) + continue; + if (pid <= 0) return; @@ -416,14 +331,17 @@ static void uloop_handle_processes(void) } -static void uloop_handle_sigint(int signo) +static void uloop_handle_signal(int signo) { - uloop_cancelled = true; -} - -static void uloop_sigchld(int signo) -{ - do_sigchld = true; + switch (signo) { + case SIGINT: + case SIGQUIT: + case SIGTERM: + uloop_cancelled = true; + break; + case SIGCHLD: + do_sigchld = true; + } } static void uloop_install_handler(int signum, void (*handler)(int), struct sigaction* old, bool add) @@ -474,11 +392,14 @@ 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; + static struct sigaction old_sigint, old_sigchld, old_sigterm, old_sigquit; - 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_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_ignore_signal(SIGPIPE, add); } @@ -565,6 +486,11 @@ void uloop_run(void) void uloop_done(void) { + if (signal_fd >= 0) { + close(signal_fd); + signal_fd = -1; + } + if (poll_fd < 0) return;