X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=scheduler%2Fselect.c;h=d302db0af8e7459b4b4cfa704225ca94f4f53822;hb=55516fd3bc9668b4f055220d3eb19c888f8cf1c2;hp=c72adbdc98fb35f91651f268bf663e6ce0868dde;hpb=f7deaa1a21758ec90bf23314af018481ea8aea7f;p=thirdparty%2Fcups.git diff --git a/scheduler/select.c b/scheduler/select.c index c72adbdc9..d302db0af 100644 --- a/scheduler/select.c +++ b/scheduler/select.c @@ -1,37 +1,16 @@ /* - * "$Id: select.c 6166 2006-12-29 20:35:18Z mike $" + * "$Id$" * - * Select abstraction functions for the Common UNIX Printing System (CUPS). + * Select abstraction functions for the CUPS scheduler. * - * Copyright 2006 by Easy Software Products. + * Copyright 2007-2014 by Apple Inc. + * Copyright 2006-2007 by Easy Software Products. * - * These coded instructions, statements, and computer programs are the - * property of Easy Software Products and are protected by Federal - * copyright law. Distribution and use rights are outlined in the file - * "LICENSE.txt" which should have been included with this file. If this - * file is missing or damaged please contact Easy Software Products - * at: - * - * Attn: CUPS Licensing Information - * Easy Software Products - * 44141 Airport View Drive, Suite 204 - * Hollywood, Maryland 20636 USA - * - * Voice: (301) 373-9600 - * EMail: cups-info@cups.org - * WWW: http://www.cups.org - * - * Contents: - * - * cupsdAddSelect() - Add a file descriptor to the list. - * cupsdDoSelect() - Do a select-like operation. - * cupsdIsSelecting() - Determine whether we are monitoring a file - * descriptor. - * cupsdRemoveSelect() - Remove a file descriptor from the list. - * cupsdStartSelect() - Initialize the file polling engine. - * cupsdStopSelect() - Shutdown the file polling engine. - * compare_fds() - Compare file descriptors. - * find_fd() - Find an existing file descriptor record. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -42,13 +21,12 @@ #ifdef HAVE_EPOLL # include +# include #elif defined(HAVE_KQUEUE) # include # include #elif defined(HAVE_POLL) -# include -#elif defined(__hpux) -# include +# include #else # include #endif /* HAVE_EPOLL */ @@ -57,15 +35,14 @@ /* * Design Notes for Poll/Select API in CUPSD * ----------------------------------------- - * + * * SUPPORTED APIS - * + * * OS select poll epoll kqueue /dev/poll * -------------- ------ ------ ------ ------ --------- * AIX YES YES NO NO NO * FreeBSD YES YES NO YES NO * HP-UX YES YES NO NO NO - * IRIX YES YES NO NO NO * Linux YES YES YES NO NO * MacOS X YES YES NO YES NO * NetBSD YES YES NO YES NO @@ -73,34 +50,35 @@ * Solaris YES YES NO NO YES * Tru64 YES YES NO NO NO * Windows YES NO NO NO NO - * - * + * + * * HIGH-LEVEL API - * + * * typedef void (*cupsd_selfunc_t)(void *data); - * + * * void cupsdStartSelect(void); * void cupsdStopSelect(void); * void cupsdAddSelect(int fd, cupsd_selfunc_t read_cb, * cupsd_selfunc_t write_cb, void *data); * void cupsdRemoveSelect(int fd); * int cupsdDoSelect(int timeout); - * - * + * + * * IMPLEMENTATION STRATEGY - * + * * 0. Common Stuff * a. CUPS array of file descriptor to callback functions - * and data. - * b. cupsdStartSelect() creates the array - * c. cupsdStopSelect() destroys the array and all elements. + * and data + temporary array of removed fd's. + * b. cupsdStartSelect() creates the arrays + * c. cupsdStopSelect() destroys the arrays and all elements. * d. cupsdAddSelect() adds to the array and allocates a * new callback element. - * e. cupsdRemoveSelect() removes from the array and frees - * the callback element. + * e. cupsdRemoveSelect() removes from the active array and + * adds to the inactive array. * f. _cupsd_fd_t provides a reference-counted structure for * tracking file descriptors that are monitored. - * + * g. cupsdDoSelect() frees all inactive FDs. + * * 1. select() O(n) * a. Input/Output fd_set variables, copied to working * copies and then used with select(). @@ -110,7 +88,7 @@ * working sets. * d. cupsdStopSelect() frees all of the memory used by the * CUPS array and fd_set's. - * + * * 2. poll() - O(n log n) * a. Regular array of pollfd, sorted the same as the CUPS * array. @@ -124,7 +102,7 @@ * e. cupsdRemoveSelect() flags the pollfd array as invalid. * f. cupsdStopSelect() frees all of the memory used by the * CUPS array and pollfd array. - * + * * 3. epoll() - O(n) * a. cupsdStartSelect() creates epoll file descriptor using * epoll_create() with the maximum fd count, and @@ -140,10 +118,10 @@ * the callback record. * d. cupsdStopSelect() closes the epoll file descriptor and * frees all of the memory used by the event buffer. - * + * * 4. kqueue() - O(n) * b. cupsdStartSelect() creates kqueue file descriptor - * using kqyeue() function and allocates a global event + * using kqueue() function and allocates a global event * buffer. * c. cupsdAdd/RemoveSelect() uses EV_SET and kevent() to * register the changes. The event user data field is a @@ -151,9 +129,9 @@ * d. cupsdDoSelect() uses kevent() to poll for events and * loops through the events, using the user data field to * find the callback record. - * e. cupsdStopSelect() closes the kqyeye() file descriptor + * e. cupsdStopSelect() closes the kqueue() file descriptor * and frees all of the memory used by the event buffer. - * + * * 5. /dev/poll - O(n log n) - NOT YET IMPLEMENTED * a. cupsdStartSelect() opens /dev/poll and allocates an * array of pollfd structs; on failure to open /dev/poll, @@ -175,8 +153,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 @@ -217,11 +195,12 @@ typedef struct _cupsd_fd_s */ static cups_array_t *cupsd_fds = NULL; +#if defined(HAVE_EPOLL) || defined(HAVE_KQUEUE) +static cups_array_t *cupsd_inactive_fds = NULL; +static int cupsd_in_select = 0; +#endif /* HAVE_EPOLL || HAVE_KQUEUE */ -#ifdef HAVE_EPOLL -static int cupsd_epoll_fd = -1; -static struct epoll_event *cupsd_epoll_events = NULL; -#elif defined(HAVE_KQUEUE) +#ifdef HAVE_KQUEUE static int cupsd_kqueue_fd = -1, cupsd_kqueue_changes = 0; static struct kevent *cupsd_kqueue_events = NULL; @@ -229,12 +208,16 @@ static struct kevent *cupsd_kqueue_events = NULL; 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 */ #else /* select() */ static fd_set cupsd_global_input, cupsd_global_output, cupsd_current_input, cupsd_current_output; -#endif /* HAVE_EPOLL */ +#endif /* HAVE_KQUEUE */ /* @@ -261,7 +244,9 @@ cupsdAddSelect(int fd, /* I - File descriptor */ void *data) /* I - Data to pass to callback */ { _cupsd_fd_t *fdptr; /* File descriptor record */ +#ifdef HAVE_EPOLL int added; /* 1 if added, 0 if modified */ +#endif /* HAVE_EPOLL */ /* @@ -269,7 +254,7 @@ cupsdAddSelect(int fd, /* I - File descriptor */ */ cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdAddSelect: fd=%d, read_cb=%p, write_cb=%p, data=%p", + "cupsdAddSelect(fd=%d, read_cb=%p, write_cb=%p, data=%p)", fd, read_cb, write_cb, data); if (fd < 0) @@ -298,31 +283,16 @@ cupsdAddSelect(int fd, /* I - File descriptor */ return (0); } +#ifdef HAVE_EPOLL added = 1; } else added = 0; - -#ifdef HAVE_EPOLL - { - 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); +#else } +#endif /* HAVE_EPOLL */ -#elif defined(HAVE_KQUEUE) +#ifdef HAVE_KQUEUE { struct kevent event; /* Event data */ struct timespec timeout; /* Timeout value */ @@ -340,8 +310,7 @@ cupsdAddSelect(int fd, /* I - File descriptor */ if (kevent(cupsd_kqueue_fd, &event, 1, NULL, 0, &timeout)) { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdAddSelect: kevent() returned %s", + cupsdLogMessage(CUPSD_LOG_EMERG, "kevent() returned %s", strerror(errno)); return (0); } @@ -356,8 +325,7 @@ cupsdAddSelect(int fd, /* I - File descriptor */ if (kevent(cupsd_kqueue_fd, &event, 1, NULL, 0, &timeout)) { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdAddSelect: kevent() returned %s", + cupsdLogMessage(CUPSD_LOG_EMERG, "kevent() returned %s", strerror(errno)); return (0); } @@ -365,6 +333,33 @@ cupsdAddSelect(int fd, /* I - File descriptor */ } #elif defined(HAVE_POLL) +# 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; + cupsd_update_pollfds = 1; + } + } + else +# endif /* HAVE_EPOLL */ + cupsd_update_pollfds = 1; #else /* select() */ @@ -374,33 +369,21 @@ cupsdAddSelect(int fd, /* I - File descriptor */ */ if (read_cb) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdAddSelect: Adding fd %d to input set...", fd); FD_SET(fd, &cupsd_global_input); - } else { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdAddSelect: Removing fd %d from input set...", fd); FD_CLR(fd, &cupsd_global_input); FD_CLR(fd, &cupsd_current_input); } if (write_cb) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdAddSelect: Adding fd %d to output set...", fd); FD_SET(fd, &cupsd_global_output); - } else { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdAddSelect: Removing fd %d from output set...", fd); 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... @@ -423,56 +406,13 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */ { int nfds; /* Number of file descriptors */ _cupsd_fd_t *fdptr; /* Current file descriptor */ -#ifdef HAVE_EPOLL - 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); - - 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; - - 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) +#ifdef HAVE_KQUEUE int i; /* Looping var */ struct kevent *event; /* Current event */ struct timespec ktimeout; /* kevent() timeout */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdDoSelect: polling %d fds for %ld seconds...", - cupsArrayCount(cupsd_fds), timeout); + cupsd_in_select = 1; if (timeout >= 0 && timeout < 86400) { @@ -485,34 +425,23 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */ else nfds = kevent(cupsd_kqueue_fd, NULL, 0, cupsd_kqueue_events, MaxFDs, NULL); - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdDoSelect: kevent(%d, ..., %d, ...) returned %d...", - cupsd_kqueue_fd, MaxFDs, nfds); - cupsd_kqueue_changes = 0; for (i = nfds, event = cupsd_kqueue_events; i > 0; i --, event ++) { fdptr = (_cupsd_fd_t *)event->udata; - cupsdLogMessage(CUPSD_LOG_DEBUG2, "event->filter=%d, event->ident=%d", - event->filter, (int)event->ident); + if (cupsArrayFind(cupsd_inactive_fds, fdptr)) + continue; retain_fd(fdptr); if (fdptr->read_cb && event->filter == EVFILT_READ) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Read on fd %d...", - fdptr->fd); (*(fdptr->read_cb))(fdptr->data); - } - if (fdptr->write_cb && event->filter == EVFILT_WRITE) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Write on fd %d...", - fdptr->fd); + if (fdptr->use > 1 && fdptr->write_cb && event->filter == EVFILT_WRITE && + !cupsArrayFind(cupsd_inactive_fds, fdptr)) (*(fdptr->write_cb))(fdptr->data); - } release_fd(fdptr); } @@ -522,6 +451,53 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */ int count; /* Number of file descriptors */ +# ifdef HAVE_EPOLL + cupsd_in_select = 1; + + 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); + + 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))) + (*(fdptr->read_cb))(fdptr->data); + + if (fdptr->use > 1 && fdptr->write_cb && + (event->events & (EPOLLOUT | EPOLLERR | EPOLLHUP)) && + !cupsArrayFind(cupsd_inactive_fds, fdptr)) + (*(fdptr->write_cb))(fdptr->data); + + release_fd(fdptr); + } + + goto release_inactive; + } + } +# endif /* HAVE_EPOLL */ + count = cupsArrayCount(cupsd_fds); if (cupsd_update_pollfds) @@ -532,8 +508,6 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */ cupsd_update_pollfds = 0; - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Updating pollfd array..."); - /* * (Re)allocate memory as needed... */ @@ -544,15 +518,13 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */ if (cupsd_pollfds) - pfd = realloc(cupsd_pollfds, allocfds * sizeof(struct pollfd)); + pfd = realloc(cupsd_pollfds, (size_t)allocfds * sizeof(struct pollfd)); else - pfd = malloc(allocfds * sizeof(struct pollfd)); + pfd = malloc((size_t)allocfds * sizeof(struct pollfd)); if (!pfd) { - cupsdLogMessage(CUPSD_LOG_EMERG, - "Unable to allocate %d bytes for polling!", - (int)(allocfds * sizeof(struct pollfd))); + cupsdLogMessage(CUPSD_LOG_EMERG, "Unable to allocate %d bytes for polling.", (int)((size_t)allocfds * sizeof(struct pollfd))); return (-1); } @@ -580,17 +552,10 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */ } } - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdDoSelect: polling %d fds for %ld seconds...", - count, timeout); - if (timeout >= 0 && timeout < 86400) - nfds = poll(cupsd_pollfds, count, timeout * 1000); + nfds = poll(cupsd_pollfds, (nfds_t)count, timeout * 1000); else - nfds = poll(cupsd_pollfds, count, -1); - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: poll() returned %d...", - nfds); + nfds = poll(cupsd_pollfds, (nfds_t)count, -1); if (nfds > 0) { @@ -600,10 +565,6 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */ for (pfd = cupsd_pollfds; count > 0; pfd ++, count --) { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdDoSelect: pollfds[%d]={fd=%d, revents=%x}", - pfd - cupsd_pollfds, pfd->fd, pfd->revents); - if (!pfd->revents) continue; @@ -613,18 +574,11 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */ retain_fd(fdptr); if (fdptr->read_cb && (pfd->revents & (POLLIN | POLLERR | POLLHUP))) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Read on fd %d...", - fdptr->fd); (*(fdptr->read_cb))(fdptr->data); - } - if (fdptr->write_cb && (pfd->revents & (POLLOUT | POLLERR | POLLHUP))) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Write on fd %d...", - fdptr->fd); + if (fdptr->use > 1 && fdptr->write_cb && + (pfd->revents & (POLLOUT | POLLERR | POLLHUP))) (*(fdptr->write_cb))(fdptr->data); - } release_fd(fdptr); } @@ -651,10 +605,6 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */ cupsd_current_input = cupsd_global_input; cupsd_current_output = cupsd_global_output; - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdDoSelect: selecting %d fds for %ld seconds...", - maxfd, timeout); - if (timeout >= 0 && timeout < 86400) { stimeout.tv_sec = timeout; @@ -667,9 +617,6 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */ nfds = select(maxfd, &cupsd_current_input, &cupsd_current_output, NULL, NULL); - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: select() returned %d...", - nfds); - if (nfds > 0) { /* @@ -683,24 +630,37 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */ retain_fd(fdptr); if (fdptr->read_cb && FD_ISSET(fdptr->fd, &cupsd_current_input)) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Read on fd %d...", - fdptr->fd); (*(fdptr->read_cb))(fdptr->data); - } - if (fdptr->write_cb && FD_ISSET(fdptr->fd, &cupsd_current_output)) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Write on fd %d...", - fdptr->fd); + if (fdptr->use > 1 && fdptr->write_cb && + FD_ISSET(fdptr->fd, &cupsd_current_output)) (*(fdptr->write_cb))(fdptr->data); - } release_fd(fdptr); } } -#endif /* HAVE_EPOLL */ +#endif /* HAVE_KQUEUE */ + +#if defined(HAVE_EPOLL) || defined(HAVE_KQUEUE) + /* + * Release all inactive file descriptors... + */ + +# ifndef HAVE_KQUEUE + release_inactive: +# endif /* !HAVE_KQUEUE */ + + cupsd_in_select = 0; + + for (fdptr = (_cupsd_fd_t *)cupsArrayFirst(cupsd_inactive_fds); + fdptr; + fdptr = (_cupsd_fd_t *)cupsArrayNext(cupsd_inactive_fds)) + { + cupsArrayRemove(cupsd_inactive_fds, fdptr); + release_fd(fdptr); + } +#endif /* HAVE_EPOLL || HAVE_KQUEUE */ /* * Return the number of file descriptors handled... @@ -710,6 +670,7 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */ } +#ifdef CUPSD_IS_SELECTING /* * 'cupsdIsSelecting()' - Determine whether we are monitoring a file * descriptor. @@ -720,6 +681,7 @@ cupsdIsSelecting(int fd) /* I - File descriptor */ { return (find_fd(fd) != NULL); } +#endif /* CUPSD_IS_SELECTING */ /* @@ -744,7 +706,7 @@ cupsdRemoveSelect(int fd) /* I - File descriptor */ * Range check input... */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdRemoveSelect: fd=%d", fd); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdRemoveSelect(fd=%d)", fd); if (fd < 0) return; @@ -757,7 +719,12 @@ cupsdRemoveSelect(int fd) /* I - File descriptor */ 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; @@ -769,10 +736,9 @@ cupsdRemoveSelect(int fd) /* I - File descriptor */ if (kevent(cupsd_kqueue_fd, &event, 1, NULL, 0, &timeout)) { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdRemoveSelect: kevent() returned %s", + cupsdLogMessage(CUPSD_LOG_EMERG, "kevent() returned %s", strerror(errno)); - return; + goto cleanup; } } @@ -782,14 +748,12 @@ cupsdRemoveSelect(int fd) /* I - File descriptor */ if (kevent(cupsd_kqueue_fd, &event, 1, NULL, 0, &timeout)) { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdRemoveSelect: kevent() returned %s", + cupsdLogMessage(CUPSD_LOG_EMERG, "kevent() returned %s", strerror(errno)); - return; + goto cleanup; } } - #elif defined(HAVE_POLL) /* * Update the pollfds array... @@ -798,20 +762,29 @@ cupsdRemoveSelect(int fd) /* I - File descriptor */ cupsd_update_pollfds = 1; #else /* select() */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdRemoveSelect: Removing fd %d from input and output " - "sets...", fd); FD_CLR(fd, &cupsd_global_input); FD_CLR(fd, &cupsd_global_output); FD_CLR(fd, &cupsd_current_input); FD_CLR(fd, &cupsd_current_output); #endif /* HAVE_EPOLL */ +#ifdef HAVE_KQUEUE + cleanup: +#endif /* HAVE_KQUEUE */ + /* - * Remove the file descriptor for from the FD array... + * Remove the file descriptor from the active array and add to the + * inactive array (or release, if we don't need the inactive array...) */ cupsArrayRemove(cupsd_fds, fdptr); + +#if defined(HAVE_EPOLL) || defined(HAVE_KQUEUE) + if (cupsd_in_select) + cupsArrayAdd(cupsd_inactive_fds, fdptr); + else +#endif /* HAVE_EPOLL || HAVE_KQUEUE */ + release_fd(fdptr); } @@ -823,16 +796,23 @@ cupsdRemoveSelect(int fd) /* I - File descriptor */ void cupsdStartSelect(void) { + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdStartSelect()"); + cupsd_fds = cupsArrayNew((cups_array_func_t)compare_fds, NULL); +#if defined(HAVE_EPOLL) || defined(HAVE_KQUEUE) + cupsd_inactive_fds = cupsArrayNew((cups_array_func_t)compare_fds, NULL); +#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((size_t)MaxFDs, sizeof(struct epoll_event)); + cupsd_update_pollfds = 0; #elif defined(HAVE_KQUEUE) cupsd_kqueue_fd = kqueue(); cupsd_kqueue_changes = 0; - cupsd_kqueue_events = calloc(MaxFDs, sizeof(struct kevent)); + cupsd_kqueue_events = calloc((size_t)MaxFDs, sizeof(struct kevent)); #elif defined(HAVE_POLL) cupsd_update_pollfds = 0; @@ -854,6 +834,8 @@ cupsdStopSelect(void) _cupsd_fd_t *fdptr; /* Current file descriptor */ + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdStopSelect()"); + for (fdptr = (_cupsd_fd_t *)cupsArrayFirst(cupsd_fds); fdptr; fdptr = (_cupsd_fd_t *)cupsArrayNext(cupsd_fds)) @@ -862,20 +844,12 @@ cupsdStopSelect(void) cupsArrayDelete(cupsd_fds); cupsd_fds = NULL; -#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; - } +#if defined(HAVE_EPOLL) || defined(HAVE_KQUEUE) + cupsArrayDelete(cupsd_inactive_fds); + cupsd_inactive_fds = NULL; +#endif /* HAVE_EPOLL || HAVE_KQUEUE */ -#elif defined(HAVE_KQUEUE) +#ifdef HAVE_KQUEUE if (cupsd_kqueue_events) { free(cupsd_kqueue_events); @@ -891,6 +865,20 @@ cupsdStopSelect(void) 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); @@ -942,5 +930,5 @@ find_fd(int fd) /* I - File descriptor */ /* - * End of "$Id: select.c 6166 2006-12-29 20:35:18Z mike $". + * End of "$Id$". */