Index: server/mpm/prefork/prefork.c =================================================================== --- server/mpm/prefork/prefork.c (Revision 820763) +++ server/mpm/prefork/prefork.c (Arbeitskopie) @@ -462,6 +462,9 @@ return 0; } +#if !defined(APR_MSG_PEEK) && defined(MSG_PEEK) +#define APR_MSG_PEEK MSG_PEEK +#endif static void child_main(int child_num_arg) { @@ -474,7 +477,14 @@ ap_sb_handle_t *sbh; apr_bucket_alloc_t *bucket_alloc; int last_poll_idx = 0; +#if defined(APR_MSG_PEEK) + apr_pollfd_t pfds[1]; + apr_int32_t nfds; + pfds[0].reqevents = APR_POLLIN; + pfds[0].desc_type = APR_POLL_SOCKET; +#endif + mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this * child initializes */ @@ -652,6 +662,44 @@ continue; } +#if defined(APR_MSG_PEEK) + if (csd) { + /* + * Check if our freshly accepted socket is already closed + * by the remote side. Processing such a closed socket + * blocks us unnecessarily until it times out. + */ + pfds[0].desc.s = csd; + do { + status = apr_poll(&pfds[0], 1, &nfds, 0); + } while (APR_STATUS_IS_EINTR(status)); + + if (status == APR_SUCCESS && nfds == 1 && + pfds[0].rtnevents == APR_POLLIN) { + apr_sockaddr_t unused; + apr_size_t len = 1; + char buf[1]; + /* + * The socket might be closed in which case + * the poll will return POLLIN. + * If there is no data available the socket + * is closed. + */ + status = apr_socket_recvfrom(&unused, csd, APR_MSG_PEEK, + &buf[0], &len); + if (!(status == APR_SUCCESS && len)) { + apr_socket_close(csd); + continue; + } + } + else if (!(APR_STATUS_IS_EAGAIN(status) + || APR_STATUS_IS_TIMEUP(status))) { + apr_socket_close(csd); + continue; + } + } +#endif + /* * We now have a connection, so set it up with the appropriate * socket options, file descriptors, and read/write buffers. Index: server/mpm/worker/worker.c =================================================================== --- server/mpm/worker/worker.c (Revision 820763) +++ server/mpm/worker/worker.c (Arbeitskopie) @@ -590,6 +590,10 @@ */ } +#if !defined(APR_MSG_PEEK) && defined(MSG_PEEK) +#define APR_MSG_PEEK MSG_PEEK +#endif + static void *listener_thread(apr_thread_t *thd, void * dummy) { proc_info * ti = dummy; @@ -602,7 +606,14 @@ ap_listen_rec *lr; int have_idle_worker = 0; int last_poll_idx = 0; +#if defined(APR_MSG_PEEK) + apr_pollfd_t pfds[1]; + apr_int32_t nfds; + pfds[0].reqevents = APR_POLLIN; + pfds[0].desc_type = APR_POLL_SOCKET; +#endif + free(ti); /* ### check the status */ @@ -748,6 +759,45 @@ resource_shortage = 1; signal_threads(ST_GRACEFUL); } + +#if defined(APR_MSG_PEEK) + if (csd) { + /* + * Check if our freshly accepted socket is already closed + * by the remote side. Dispatching such a closed socket + * to the workers blocks them unnecessarily until they + * timeout. + */ + pfds[0].desc.s = csd; + do { + rv = apr_poll(&pfds[0], 1, &nfds, 0); + } while (APR_STATUS_IS_EINTR(rv)); + + if (rv == APR_SUCCESS && nfds == 1 && + pfds[0].rtnevents == APR_POLLIN) { + apr_sockaddr_t unused; + apr_size_t len = 1; + char buf[1]; + /* + * The socket might be closed in which case + * the poll will return POLLIN. + * If there is no data available the socket + * is closed. + */ + rv = apr_socket_recvfrom(&unused, csd, APR_MSG_PEEK, + &buf[0], &len); + if (!(rv == APR_SUCCESS && len)) { + apr_socket_close(csd); + csd = NULL; + } + } + else if (!(APR_STATUS_IS_EAGAIN(rv) || APR_STATUS_IS_TIMEUP(rv))) { + apr_socket_close(csd); + csd = NULL; + } + } +#endif + if ((rv = SAFE_ACCEPT(apr_proc_mutex_unlock(accept_mutex))) != APR_SUCCESS) { int level = APLOG_EMERG; Index: server/mpm/experimental/event/event.c =================================================================== --- server/mpm/experimental/event/event.c (Revision 820763) +++ server/mpm/experimental/event/event.c (Arbeitskopie) @@ -802,6 +802,10 @@ } } +#if !defined(APR_MSG_PEEK) && defined(MSG_PEEK) +#define APR_MSG_PEEK MSG_PEEK +#endif + static void *listener_thread(apr_thread_t * thd, void *dummy) { apr_status_t rc; @@ -819,7 +823,14 @@ apr_interval_time_t timeout_interval; apr_time_t timeout_time; listener_poll_type *pt; +#if defined(APR_MSG_PEEK) + apr_pollfd_t pfds[1]; + apr_int32_t nfds; + pfds[0].reqevents = APR_POLLIN; + pfds[0].desc_type = APR_POLL_SOCKET; +#endif + free(ti); /* We set this to force apr_pollset to wakeup if there hasn't been any IO @@ -991,6 +1002,45 @@ signal_threads(ST_GRACEFUL); } +#if defined(APR_MSG_PEEK) + if (csd) { + /* + * Check if our freshly accepted socket is already closed + * by the remote side. Dispatching such a closed socket + * to the workers blocks them unnecessarily until they + * timeout. + */ + pfds[0].desc.s = csd; + do { + rc = apr_poll(&pfds[0], 1, &nfds, 0); + } while (APR_STATUS_IS_EINTR(rc)); + + if (rc == APR_SUCCESS && nfds == 1 && + pfds[0].rtnevents == APR_POLLIN) { + apr_sockaddr_t unused; + apr_size_t len = 1; + char buf[1]; + /* + * The socket might be closed in which case + * the poll will return POLLIN. + * If there is no data available the socket + * is closed. + */ + rc = apr_socket_recvfrom(&unused, csd, APR_MSG_PEEK, + &buf[0], &len); + if (!(rc == APR_SUCCESS && len)) { + apr_socket_close(csd); + csd = NULL; + } + } + else if (!(APR_STATUS_IS_EAGAIN(rc) + || APR_STATUS_IS_TIMEUP(rc))) { + apr_socket_close(csd); + csd = NULL; + } + } +#endif + if (csd != NULL) { rc = ap_queue_push(worker_queue, csd, NULL, ptrans); if (rc != APR_SUCCESS) {