Index: select.c =================================================================== --- select.c (revision 7084) +++ select.c (working copy) @@ -33,6 +33,7 @@ #ifdef HAVE_EPOLL # include +# include #elif defined(HAVE_KQUEUE) # include # include @@ -167,8 +168,8 @@ * * In tests using the "make test" target with option 0 (keep cupsd * running) and the "testspeed" program with "-c 50 -r 1000", epoll() - * performed 5.5% slower select(), followed by kqueue() at 16% slower - * than select() and poll() at 18% slower than select(). Similar + * performed 5.5% slower than select(), followed by kqueue() at 16% + * slower than select() and poll() at 18% slower than select(). Similar * results were seen with twice the number of client connections. * * The epoll() and kqueue() performance is likely limited by the @@ -214,17 +215,18 @@ static int cupsd_in_select = 0; #endif /* HAVE_EPOLL || HAVE_KQUEUE */ -#ifdef HAVE_EPOLL +#ifdef HAVE_POLL +static int cupsd_alloc_pollfds = 0, + cupsd_update_pollfds = 0; +static struct pollfd *cupsd_pollfds = NULL; +# ifdef HAVE_EPOLL static int cupsd_epoll_fd = -1; static struct epoll_event *cupsd_epoll_events = NULL; +# endif /* HAVE_EPOLL */ #elif defined(HAVE_KQUEUE) static int cupsd_kqueue_fd = -1, cupsd_kqueue_changes = 0; static struct kevent *cupsd_kqueue_events = NULL; -#elif defined(HAVE_POLL) -static int cupsd_alloc_pollfds = 0, - cupsd_update_pollfds = 0; -static struct pollfd *cupsd_pollfds = NULL; #else /* select() */ static fd_set cupsd_global_input, cupsd_global_output, @@ -299,27 +301,8 @@ else added = 0; -#ifdef HAVE_EPOLL +#ifdef HAVE_KQUEUE { - struct epoll_event event; /* Event data */ - - - event.events = 0; - - if (read_cb) - event.events |= EPOLLIN; - - if (write_cb) - event.events |= EPOLLOUT; - - event.data.ptr = fdptr; - - epoll_ctl(cupsd_epoll_fd, added ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, - &event); - } - -#elif defined(HAVE_KQUEUE) - { struct kevent event; /* Event data */ struct timespec timeout; /* Timeout value */ @@ -363,6 +346,31 @@ #elif defined(HAVE_POLL) cupsd_update_pollfds = 1; +# ifdef HAVE_EPOLL + if (cupsd_epoll_fd >= 0) + { + struct epoll_event event; /* Event data */ + + + event.events = 0; + + if (read_cb) + event.events |= EPOLLIN; + + if (write_cb) + event.events |= EPOLLOUT; + + event.data.ptr = fdptr; + + if (epoll_ctl(cupsd_epoll_fd, added ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, + &event)) + { + close(cupsd_epoll_fd); + cupsd_epoll_fd = -1; + } + } +# endif /* HAVE_EPOLL */ + #else /* select() */ /* * Add or remove the file descriptor in the input and output sets @@ -396,7 +404,7 @@ FD_CLR(fd, &cupsd_global_output); FD_CLR(fd, &cupsd_current_output); } -#endif /* HAVE_EPOLL */ +#endif /* HAVE_KQUEUE */ /* * Save the (new) read and write callbacks... @@ -419,54 +427,8 @@ { int nfds; /* Number of file descriptors */ _cupsd_fd_t *fdptr; /* Current file descriptor */ -#ifdef HAVE_EPOLL +#ifdef HAVE_KQUEUE int i; /* Looping var */ - struct epoll_event *event; /* Current event */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdDoSelect: polling %d fds for %ld seconds...", - cupsArrayCount(cupsd_fds), timeout); - - cupsd_in_select = 1; - - if (timeout >= 0 && timeout < 86400) - nfds = epoll_wait(cupsd_epoll_fd, cupsd_epoll_events, MaxFDs, - timeout * 1000); - else - nfds = epoll_wait(cupsd_epoll_fd, cupsd_epoll_events, MaxFDs, -1); - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: epoll() returned %d...", - nfds); - - for (i = nfds, event = cupsd_epoll_events; i > 0; i --, event ++) - { - fdptr = (_cupsd_fd_t *)event->data.ptr; - - if (cupsArrayFind(cupsd_inactive_fds, fdptr)) - continue; - - retain_fd(fdptr); - - if (fdptr->read_cb && (event->events & (EPOLLIN | EPOLLERR | EPOLLHUP))) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Read on fd %d...", - fdptr->fd); - (*(fdptr->read_cb))(fdptr->data); - } - - if (fdptr->write_cb && (event->events & (EPOLLOUT | EPOLLERR | EPOLLHUP))) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Write on fd %d...", - fdptr->fd); - (*(fdptr->write_cb))(fdptr->data); - } - - release_fd(fdptr); - } - -#elif defined(HAVE_KQUEUE) - int i; /* Looping var */ struct kevent *event; /* Current event */ struct timespec ktimeout; /* kevent() timeout */ @@ -528,6 +490,66 @@ int count; /* Number of file descriptors */ + cupsdLogMessage(CUPSD_LOG_DEBUG2, + "cupsdDoSelect: polling %d fds for %ld seconds...", + cupsArrayCount(cupsd_fds), timeout); + + cupsd_in_select = 1; + +# ifdef HAVE_EPOLL + if (cupsd_epoll_fd >= 0) + { + int i; /* Looping var */ + struct epoll_event *event; /* Current event */ + + + if (timeout >= 0 && timeout < 86400) + nfds = epoll_wait(cupsd_epoll_fd, cupsd_epoll_events, MaxFDs, + timeout * 1000); + else + nfds = epoll_wait(cupsd_epoll_fd, cupsd_epoll_events, MaxFDs, -1); + + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: epoll() returned %d...", + nfds); + + if (nfds < 0 && errno != EINTR) + { + close(cupsd_epoll_fd); + cupsd_epoll_fd = -1; + } + else + { + for (i = nfds, event = cupsd_epoll_events; i > 0; i --, event ++) + { + fdptr = (_cupsd_fd_t *)event->data.ptr; + + if (cupsArrayFind(cupsd_inactive_fds, fdptr)) + continue; + + retain_fd(fdptr); + + if (fdptr->read_cb && (event->events & (EPOLLIN | EPOLLERR | EPOLLHUP))) + { + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Read on fd %d...", + fdptr->fd); + (*(fdptr->read_cb))(fdptr->data); + } + + if (fdptr->write_cb && (event->events & (EPOLLOUT | EPOLLERR | EPOLLHUP))) + { + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Write on fd %d...", + fdptr->fd); + (*(fdptr->write_cb))(fdptr->data); + } + + release_fd(fdptr); + } + + return (nfds); + } + } +# endif /* HAVE_EPOLL */ + count = cupsArrayCount(cupsd_fds); if (cupsd_update_pollfds) @@ -706,7 +728,7 @@ } } -#endif /* HAVE_EPOLL */ +#endif /* HAVE_KQUEUE */ #if defined(HAVE_EPOLL) || defined(HAVE_KQUEUE) /* @@ -781,7 +803,12 @@ return; #ifdef HAVE_EPOLL - epoll_ctl(cupsd_epoll_fd, EPOLL_CTL_DEL, fd, &event); + if (epoll_ctl(cupsd_epoll_fd, EPOLL_CTL_DEL, fd, &event)) + { + close(cupsd_epoll_fd); + cupsd_epoll_fd = -1; + cupsd_update_pollfds = 1; + } #elif defined(HAVE_KQUEUE) timeout.tv_sec = 0; @@ -862,8 +889,9 @@ #endif /* HAVE_EPOLL || HAVE_KQUEUE */ #ifdef HAVE_EPOLL - cupsd_epoll_fd = epoll_create(MaxFDs); - cupsd_epoll_events = calloc(MaxFDs, sizeof(struct epoll_event)); + cupsd_epoll_fd = epoll_create(MaxFDs); + cupsd_epoll_events = calloc(MaxFDs, sizeof(struct epoll_event)); + cupsd_update_pollfds = 0; #elif defined(HAVE_KQUEUE) cupsd_kqueue_fd = kqueue(); @@ -903,20 +931,7 @@ cupsd_inactive_fds = NULL; #endif /* HAVE_EPOLL || HAVE_KQUEUE */ -#ifdef HAVE_EPOLL - if (cupsd_epoll_events) - { - free(cupsd_epoll_events); - cupsd_epoll_events = NULL; - } - - if (cupsd_epoll_fd >= 0) - { - close(cupsd_epoll_fd); - cupsd_epoll_fd = -1; - } - -#elif defined(HAVE_KQUEUE) +#ifdef HAVE_KQUEUE if (cupsd_kqueue_events) { free(cupsd_kqueue_events); @@ -932,6 +947,20 @@ cupsd_kqueue_changes = 0; #elif defined(HAVE_POLL) +# ifdef HAVE_EPOLL + if (cupsd_epoll_events) + { + free(cupsd_epoll_events); + cupsd_epoll_events = NULL; + } + + if (cupsd_epoll_fd >= 0) + { + close(cupsd_epoll_fd); + cupsd_epoll_fd = -1; + } +# endif /* HAVE_EPOLL */ + if (cupsd_pollfds) { free(cupsd_pollfds); Index: select.c =================================================================== --- select.c (revision 7087) +++ select.c (working copy) @@ -344,8 +344,6 @@ } #elif defined(HAVE_POLL) - cupsd_update_pollfds = 1; - # ifdef HAVE_EPOLL if (cupsd_epoll_fd >= 0) { @@ -366,11 +364,15 @@ &event)) { close(cupsd_epoll_fd); - cupsd_epoll_fd = -1; + cupsd_epoll_fd = -1; + cupsd_update_pollfds = 1; } } + else # endif /* HAVE_EPOLL */ + cupsd_update_pollfds = 1; + #else /* select() */ /* * Add or remove the file descriptor in the input and output sets @@ -494,9 +496,9 @@ "cupsdDoSelect: polling %d fds for %ld seconds...", cupsArrayCount(cupsd_fds), timeout); +# ifdef HAVE_EPOLL cupsd_in_select = 1; -# ifdef HAVE_EPOLL if (cupsd_epoll_fd >= 0) { int i; /* Looping var */ @@ -545,7 +547,7 @@ release_fd(fdptr); } - return (nfds); + goto release_inactive; } } # endif /* HAVE_EPOLL */ @@ -735,6 +737,8 @@ * Release all inactive file descriptors... */ + release_inactive: + cupsd_in_select = 0; for (fdptr = (_cupsd_fd_t *)cupsArrayFirst(cupsd_inactive_fds);