From 67b11d5368e123a33ae727275df59939af15403c Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 15 Feb 2022 13:05:37 +0000 Subject: On '1.8.x-r1897895' branch: Backport r1897895 from trunk. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/branches/1.8.x-r1897895@1898104 13f79535-47bb-0310-9956-ffa450edef68 --- CMakeLists.txt | 1 + file_io/win32/pipe.c | 208 ------------------------------ file_io/win32/readwrite.c | 42 +----- include/arch/unix/apr_arch_poll_private.h | 23 +++- include/arch/win32/apr_arch_file_io.h | 11 +- include/arch/win32/apr_arch_networkio.h | 8 ++ network_io/win32/socket_pipe.c | 195 ++++++++++++++++++++++++++++ poll/unix/poll.c | 25 +++- poll/unix/pollcb.c | 25 +++- poll/unix/pollset.c | 22 +++- poll/unix/select.c | 35 +++-- poll/unix/wakeup.c | 36 ++++-- 12 files changed, 338 insertions(+), 293 deletions(-) create mode 100644 network_io/win32/socket_pipe.c diff --git a/CMakeLists.txt b/CMakeLists.txt index b4632c3c0..87f4ea8c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -174,6 +174,7 @@ SET(APR_SOURCES network_io/unix/sockaddr.c network_io/unix/socket_util.c network_io/win32/sendrecv.c + network_io/win32/socket_pipe.c network_io/win32/sockets.c network_io/win32/sockopt.c passwd/apr_getpass.c diff --git a/file_io/win32/pipe.c b/file_io/win32/pipe.c index 7dcbfb00e..e898b2d13 100644 --- a/file_io/win32/pipe.c +++ b/file_io/win32/pipe.c @@ -272,211 +272,3 @@ APR_DECLARE(apr_status_t) apr_os_pipe_put(apr_file_t **file, { return apr_os_pipe_put_ex(file, thefile, 0, pool); } - -static apr_status_t create_socket_pipe(SOCKET *rd, SOCKET *wr) -{ - static int id = 0; - FD_SET rs; - SOCKET ls; - struct timeval socktm; - struct sockaddr_in pa; - struct sockaddr_in la; - struct sockaddr_in ca; - int nrd; - apr_status_t rv = APR_SUCCESS; - int ll = sizeof(la); - int lc = sizeof(ca); - unsigned long bm = 1; - int uid[2]; - int iid[2]; - - *rd = INVALID_SOCKET; - *wr = INVALID_SOCKET; - - /* Create the unique socket identifier - * so that we know the connection originated - * from us. - */ - uid[0] = getpid(); - uid[1] = id++; - if ((ls = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { - return apr_get_netos_error(); - } - - pa.sin_family = AF_INET; - pa.sin_port = 0; - pa.sin_addr.s_addr = inet_addr("127.0.0.1"); - - if (bind(ls, (SOCKADDR *)&pa, sizeof(pa)) == SOCKET_ERROR) { - rv = apr_get_netos_error(); - goto cleanup; - } - if (getsockname(ls, (SOCKADDR *)&la, &ll) == SOCKET_ERROR) { - rv = apr_get_netos_error(); - goto cleanup; - } - if (listen(ls, 1) == SOCKET_ERROR) { - rv = apr_get_netos_error(); - goto cleanup; - } - if ((*wr = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { - rv = apr_get_netos_error(); - goto cleanup; - } - if (connect(*wr, (SOCKADDR *)&la, sizeof(la)) == SOCKET_ERROR) { - rv = apr_get_netos_error(); - goto cleanup; - } - if (send(*wr, (char *)uid, sizeof(uid), 0) != sizeof(uid)) { - if ((rv = apr_get_netos_error()) == 0) { - rv = APR_EINVAL; - } - goto cleanup; - } - if (ioctlsocket(ls, FIONBIO, &bm) == SOCKET_ERROR) { - rv = apr_get_netos_error(); - goto cleanup; - } - for (;;) { - int ns; - int nc = 0; - /* Listening socket is nonblocking by now. - * The accept should create the socket - * immediatelly because we are connected already. - * However on buys systems this can take a while - * until winsock gets a chance to handle the events. - */ - FD_ZERO(&rs); - FD_SET(ls, &rs); - - socktm.tv_sec = 1; - socktm.tv_usec = 0; - if ((ns = select(0, &rs, NULL, NULL, &socktm)) == SOCKET_ERROR) { - /* Accept still not signaled */ - Sleep(100); - continue; - } - if (ns == 0) { - /* No connections in the last second */ - continue; - } - if ((*rd = accept(ls, (SOCKADDR *)&ca, &lc)) == INVALID_SOCKET) { - rv = apr_get_netos_error(); - goto cleanup; - } - /* Verify the connection by reading/waiting for the identification */ - bm = 0; - if (ioctlsocket(*rd, FIONBIO, &bm) == SOCKET_ERROR) { - rv = apr_get_netos_error(); - goto cleanup; - } - nrd = recv(*rd, (char *)iid, sizeof(iid), 0); - if (nrd == SOCKET_ERROR) { - rv = apr_get_netos_error(); - goto cleanup; - } - if (nrd == (int)sizeof(uid) && memcmp(iid, uid, sizeof(uid)) == 0) { - /* Got the right identifier, put the poll()able read side of - * the pipe in nonblocking mode and return. - */ - bm = 1; - if (ioctlsocket(*rd, FIONBIO, &bm) == SOCKET_ERROR) { - rv = apr_get_netos_error(); - goto cleanup; - } - break; - } - closesocket(*rd); - } - /* We don't need the listening socket any more */ - closesocket(ls); - return 0; - -cleanup: - /* Don't leak resources */ - closesocket(ls); - if (*rd != INVALID_SOCKET) - closesocket(*rd); - if (*wr != INVALID_SOCKET) - closesocket(*wr); - - *rd = INVALID_SOCKET; - *wr = INVALID_SOCKET; - return rv; -} - -static apr_status_t socket_pipe_cleanup(void *thefile) -{ - apr_file_t *file = thefile; - if (file->filehand != INVALID_HANDLE_VALUE) { - shutdown((SOCKET)file->filehand, SD_BOTH); - closesocket((SOCKET)file->filehand); - file->filehand = INVALID_HANDLE_VALUE; - } - return APR_SUCCESS; -} - -apr_status_t apr_file_socket_pipe_create(apr_file_t **in, - apr_file_t **out, - apr_pool_t *p) -{ - apr_status_t rv; - SOCKET rd; - SOCKET wr; - - if ((rv = create_socket_pipe(&rd, &wr)) != APR_SUCCESS) { - return rv; - } - (*in) = (apr_file_t *)apr_pcalloc(p, sizeof(apr_file_t)); - (*in)->pool = p; - (*in)->fname = NULL; - (*in)->ftype = APR_FILETYPE_SOCKET; - (*in)->timeout = 0; /* read end of the pipe is non-blocking */ - (*in)->ungetchar = -1; - (*in)->eof_hit = 0; - (*in)->filePtr = 0; - (*in)->bufpos = 0; - (*in)->dataRead = 0; - (*in)->direction = 0; - (*in)->pOverlapped = NULL; - (*in)->filehand = (HANDLE)rd; - - (*out) = (apr_file_t *)apr_pcalloc(p, sizeof(apr_file_t)); - (*out)->pool = p; - (*out)->fname = NULL; - (*out)->ftype = APR_FILETYPE_SOCKET; - (*out)->timeout = -1; - (*out)->ungetchar = -1; - (*out)->eof_hit = 0; - (*out)->filePtr = 0; - (*out)->bufpos = 0; - (*out)->dataRead = 0; - (*out)->direction = 0; - (*out)->pOverlapped = NULL; - (*out)->filehand = (HANDLE)wr; - - apr_pool_cleanup_register(p, (void *)(*in), socket_pipe_cleanup, - apr_pool_cleanup_null); - apr_pool_cleanup_register(p, (void *)(*out), socket_pipe_cleanup, - apr_pool_cleanup_null); - - return rv; -} - -apr_status_t apr_file_socket_pipe_close(apr_file_t *file) -{ - apr_status_t stat; - if (file->ftype != APR_FILETYPE_SOCKET) - return apr_file_close(file); - if ((stat = socket_pipe_cleanup(file)) == APR_SUCCESS) { - apr_pool_cleanup_kill(file->pool, file, socket_pipe_cleanup); - - if (file->mutex) { - apr_thread_mutex_destroy(file->mutex); - } - - return APR_SUCCESS; - } - return stat; -} - diff --git a/file_io/win32/readwrite.c b/file_io/win32/readwrite.c index bd4e87c9e..79a4b2b17 100644 --- a/file_io/win32/readwrite.c +++ b/file_io/win32/readwrite.c @@ -20,7 +20,6 @@ #include "apr_strings.h" #include "apr_lib.h" #include "apr_errno.h" -#include "apr_arch_networkio.h" #include "apr_arch_atime.h" #include "apr_arch_misc.h" @@ -75,23 +74,8 @@ static apr_status_t read_with_timeout(apr_file_t *file, void *buf, apr_size_t le file->pOverlapped->OffsetHigh = (DWORD)(file->filePtr >> 32); } - if (file->ftype == APR_FILETYPE_SOCKET) { - WSABUF wsaData; - DWORD flags = 0; - - wsaData.buf = (char*) buf; - wsaData.len = (u_long)len; - if (WSARecv((SOCKET)file->filehand, &wsaData, 1, &bytesread, - &flags, NULL, NULL) == SOCKET_ERROR) { - rv = apr_get_netos_error(); - bytesread = 0; - } - else { - rv = APR_SUCCESS; - } - } - else if (ReadFile(file->filehand, buf, len, - &bytesread, file->pOverlapped)) { + if (ReadFile(file->filehand, buf, len, + &bytesread, file->pOverlapped)) { rv = APR_SUCCESS; } else { @@ -315,25 +299,9 @@ APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, a if (thefile->flags & APR_FOPEN_XTHREAD) { apr_thread_mutex_unlock(thefile->mutex); } - } - else if (thefile->ftype == APR_FILETYPE_SOCKET) { - WSABUF wsaData; - DWORD flags = 0; - - wsaData.buf = (char*) buf; - wsaData.len = (u_long)*nbytes; - if (WSASend((SOCKET)thefile->filehand, &wsaData, 1, &bwrote, - flags, NULL, NULL) == SOCKET_ERROR) { - rv = apr_get_netos_error(); - bwrote = 0; - } - else { - rv = APR_SUCCESS; - } - *nbytes = bwrote; - } - else { - if (thefile->ftype != APR_FILETYPE_FILE) { + return rv; + } else { + if (thefile->ftype == APR_FILETYPE_PIPE) { rv = WriteFile(thefile->filehand, buf, (DWORD)*nbytes, &bwrote, thefile->pOverlapped); } diff --git a/include/arch/unix/apr_arch_poll_private.h b/include/arch/unix/apr_arch_poll_private.h index 8dd97d1ad..7b91963a6 100644 --- a/include/arch/unix/apr_arch_poll_private.h +++ b/include/arch/unix/apr_arch_poll_private.h @@ -81,6 +81,12 @@ #endif #endif +#ifdef WIN32 +#define WAKEUP_USES_PIPE 0 +#else +#define WAKEUP_USES_PIPE 1 +#endif + #if defined(POLLSET_USES_KQUEUE) || defined(POLLSET_USES_EPOLL) || defined(POLLSET_USES_PORT) || defined(POLLSET_USES_AIO_MSGQ) #include "apr_ring.h" @@ -121,7 +127,11 @@ struct apr_pollset_t apr_uint32_t nalloc; apr_uint32_t flags; /* Pipe descriptors used for wakeup */ +#if WAKEUP_USES_PIPE apr_file_t *wakeup_pipe[2]; +#else + apr_socket_t *wakeup_socket[2]; +#endif apr_pollfd_t wakeup_pfd; volatile apr_uint32_t wakeup_set; apr_pollset_private_t *p; @@ -150,7 +160,11 @@ struct apr_pollcb_t { apr_uint32_t nalloc; apr_uint32_t flags; /* Pipe descriptors used for wakeup */ +#if WAKEUP_USES_PIPE apr_file_t *wakeup_pipe[2]; +#else + apr_socket_t *wakeup_socket[2]; +#endif apr_pollfd_t wakeup_pfd; volatile apr_uint32_t wakeup_set; int fd; @@ -181,9 +195,16 @@ struct apr_pollcb_provider_t { * Private functions used for the implementation of both apr_pollcb_* and * apr_pollset_* */ -apr_status_t apr_poll_create_wakeup_pipe(apr_pool_t *pool, apr_pollfd_t *pfd, +#if WAKEUP_USES_PIPE +apr_status_t apr_poll_create_wakeup_pipe(apr_pool_t *pool, apr_pollfd_t *pfd, apr_file_t **wakeup_pipe); apr_status_t apr_poll_close_wakeup_pipe(apr_file_t **wakeup_pipe); void apr_poll_drain_wakeup_pipe(volatile apr_uint32_t *wakeup_set, apr_file_t **wakeup_pipe); +#else +apr_status_t apr_poll_create_wakeup_socket(apr_pool_t *pool, apr_pollfd_t *pfd, + apr_socket_t **wakeup_socket); +apr_status_t apr_poll_close_wakeup_socket(apr_socket_t **wakeup_socket); +void apr_poll_drain_wakeup_socket(volatile apr_uint32_t *wakeup_set, apr_socket_t **wakeup_socket); +#endif #endif /* APR_ARCH_POLL_PRIVATE_H */ diff --git a/include/arch/win32/apr_arch_file_io.h b/include/arch/win32/apr_arch_file_io.h index bef536450..ad8153946 100644 --- a/include/arch/win32/apr_arch_file_io.h +++ b/include/arch/win32/apr_arch_file_io.h @@ -161,8 +161,7 @@ apr_status_t more_finfo(apr_finfo_t *finfo, const void *ufile, typedef enum { APR_FILETYPE_FILE = 0, - APR_FILETYPE_PIPE, - APR_FILETYPE_SOCKET + APR_FILETYPE_PIPE } apr_filetype_e; struct apr_file_t { @@ -261,12 +260,4 @@ apr_status_t filepath_root_case(char **rootpath, char *root, apr_pool_t *p); apr_status_t file_cleanup(void *); -extern apr_status_t -apr_file_socket_pipe_create(apr_file_t **in, - apr_file_t **out, - apr_pool_t *p); - -extern apr_status_t -apr_file_socket_pipe_close(apr_file_t *file); - #endif /* ! FILE_IO_H */ diff --git a/include/arch/win32/apr_arch_networkio.h b/include/arch/win32/apr_arch_networkio.h index 04be55595..dabe35ca1 100644 --- a/include/arch/win32/apr_arch_networkio.h +++ b/include/arch/win32/apr_arch_networkio.h @@ -86,5 +86,13 @@ void apr_sockaddr_vars_set(apr_sockaddr_t *, int, apr_port_t); (skt)->options &= ~(option); \ } while (0) +extern apr_status_t +apr_socket_pipe_create(apr_socket_t **in, + apr_socket_t **out, + apr_pool_t *p); + +extern apr_status_t +apr_socket_pipe_close(apr_socket_t *socket); + #endif /* ! NETWORK_IO_H */ diff --git a/network_io/win32/socket_pipe.c b/network_io/win32/socket_pipe.c new file mode 100644 index 000000000..d9cac504b --- /dev/null +++ b/network_io/win32/socket_pipe.c @@ -0,0 +1,195 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_portable.h" + +static apr_status_t create_socket_pipe(SOCKET *rd, SOCKET *wr) +{ + FD_SET rs; + SOCKET ls; + struct timeval socktm; + struct sockaddr_in pa; + struct sockaddr_in la; + struct sockaddr_in ca; + int nrd; + apr_status_t rv; + int ll = sizeof(la); + int lc = sizeof(ca); + unsigned long bm = 1; + char uid[8]; + char iid[8]; + + *rd = INVALID_SOCKET; + *wr = INVALID_SOCKET; + + /* Create the unique socket identifier + * so that we know the connection originated + * from us. + */ + rv = apr_generate_random_bytes(uid, sizeof(uid)); + if (rv != APR_SUCCESS) { + return rv; + } + + if ((ls = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { + return apr_get_netos_error(); + } + + pa.sin_family = AF_INET; + pa.sin_port = 0; + pa.sin_addr.s_addr = inet_addr("127.0.0.1"); + + if (bind(ls, (SOCKADDR *)&pa, sizeof(pa)) == SOCKET_ERROR) { + rv = apr_get_netos_error(); + goto cleanup; + } + if (getsockname(ls, (SOCKADDR *)&la, &ll) == SOCKET_ERROR) { + rv = apr_get_netos_error(); + goto cleanup; + } + if (listen(ls, 1) == SOCKET_ERROR) { + rv = apr_get_netos_error(); + goto cleanup; + } + if ((*wr = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { + rv = apr_get_netos_error(); + goto cleanup; + } + if (connect(*wr, (SOCKADDR *)&la, sizeof(la)) == SOCKET_ERROR) { + rv = apr_get_netos_error(); + goto cleanup; + } + if (send(*wr, uid, sizeof(uid), 0) != sizeof(uid)) { + if ((rv = apr_get_netos_error()) == 0) { + rv = APR_EINVAL; + } + goto cleanup; + } + if (ioctlsocket(ls, FIONBIO, &bm) == SOCKET_ERROR) { + rv = apr_get_netos_error(); + goto cleanup; + } + for (;;) { + int ns; + int nc = 0; + /* Listening socket is nonblocking by now. + * The accept should create the socket + * immediatelly because we are connected already. + * However on buys systems this can take a while + * until winsock gets a chance to handle the events. + */ + FD_ZERO(&rs); + FD_SET(ls, &rs); + + socktm.tv_sec = 1; + socktm.tv_usec = 0; + if ((ns = select(0, &rs, NULL, NULL, &socktm)) == SOCKET_ERROR) { + /* Accept still not signaled */ + Sleep(100); + continue; + } + if (ns == 0) { + /* No connections in the last second */ + continue; + } + if ((*rd = accept(ls, (SOCKADDR *)&ca, &lc)) == INVALID_SOCKET) { + rv = apr_get_netos_error(); + goto cleanup; + } + /* Verify the connection by reading/waiting for the identification */ + bm = 0; + if (ioctlsocket(*rd, FIONBIO, &bm) == SOCKET_ERROR) { + rv = apr_get_netos_error(); + goto cleanup; + } + nrd = recv(*rd, iid, sizeof(iid), 0); + if (nrd == SOCKET_ERROR) { + rv = apr_get_netos_error(); + goto cleanup; + } + if (nrd == (int)sizeof(uid) && memcmp(iid, uid, sizeof(uid)) == 0) { + /* Got the right identifier, return. */ + break; + } + closesocket(*rd); + } + /* We don't need the listening socket any more */ + closesocket(ls); + return 0; + +cleanup: + /* Don't leak resources */ + closesocket(ls); + if (*rd != INVALID_SOCKET) + closesocket(*rd); + if (*wr != INVALID_SOCKET) + closesocket(*wr); + + *rd = INVALID_SOCKET; + *wr = INVALID_SOCKET; + return rv; +} + +static apr_status_t socket_pipe_cleanup(void *thefile) +{ + apr_socket_t *file = thefile; + if (file->socketdes != INVALID_SOCKET) { + shutdown(file->socketdes, SD_BOTH); + closesocket(file->socketdes); + file->socketdes = INVALID_SOCKET; + } + return APR_SUCCESS; +} + +apr_status_t apr_socket_pipe_create(apr_socket_t **in, + apr_socket_t **out, + apr_pool_t *p) +{ + apr_status_t rv; + SOCKET rd; + SOCKET wr; + + *in = NULL; + *out = NULL; + + if ((rv = create_socket_pipe(&rd, &wr)) != APR_SUCCESS) { + return rv; + } + apr_os_sock_put(in, &rd, p); + apr_os_sock_put(out, &wr, p); + + /* read end of the pipe is non-blocking */ + apr_socket_timeout_set(*in, 0); + + apr_pool_cleanup_register(p, (void *)(*in), socket_pipe_cleanup, + apr_pool_cleanup_null); + apr_pool_cleanup_register(p, (void *)(*out), socket_pipe_cleanup, + apr_pool_cleanup_null); + + return rv; +} + +apr_status_t apr_socket_pipe_close(apr_socket_t *socket) +{ + apr_status_t stat; + if ((stat = socket_pipe_cleanup(socket)) == APR_SUCCESS) { + apr_pool_cleanup_kill(socket->pool, socket, socket_pipe_cleanup); + + return APR_SUCCESS; + } + return stat; +} diff --git a/poll/unix/poll.c b/poll/unix/poll.c index 9b6a539e0..fdfece536 100644 --- a/poll/unix/poll.c +++ b/poll/unix/poll.c @@ -191,11 +191,7 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, #if APR_FILES_AS_SOCKETS pollset->p->pollset[pollset->nelts].fd = descriptor->desc.f->filedes; #else - if ((pollset->flags & APR_POLLSET_WAKEABLE) && - descriptor->desc.f == pollset->wakeup_pipe[0]) - pollset->p->pollset[pollset->nelts].fd = (SOCKET)descriptor->desc.f->filedes; - else - return APR_EBADF; + return APR_EBADF; #endif } pollset->p->pollset[pollset->nelts].events = @@ -276,12 +272,21 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, /* Check if the polled descriptor is our * wakeup pipe. In that case do not put it result set. */ +#if WAKEUP_USES_PIPE if ((pollset->flags & APR_POLLSET_WAKEABLE) && pollset->p->query_set[i].desc_type == APR_POLL_FILE && pollset->p->query_set[i].desc.f == pollset->wakeup_pipe[0]) { apr_poll_drain_wakeup_pipe(&pollset->wakeup_set, pollset->wakeup_pipe); rv = APR_EINTR; } +#else + if ((pollset->flags & APR_POLLSET_WAKEABLE) && + pollset->p->query_set[i].desc_type == APR_POLL_SOCKET && + pollset->p->query_set[i].desc.s == pollset->wakeup_socket[0]) { + apr_poll_drain_wakeup_socket(&pollset->wakeup_set, pollset->wakeup_socket); + rv = APR_EINTR; + } +#endif else { pollset->p->result_set[j] = pollset->p->query_set[i]; pollset->p->result_set[j].rtnevents = @@ -428,13 +433,21 @@ static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb, if (pollcb->pollset.ps[i].revents != 0) { apr_pollfd_t *pollfd = pollcb->copyset[i]; +#if WAKEUP_USES_PIPE if ((pollcb->flags & APR_POLLSET_WAKEABLE) && pollfd->desc_type == APR_POLL_FILE && pollfd->desc.f == pollcb->wakeup_pipe[0]) { apr_poll_drain_wakeup_pipe(&pollcb->wakeup_set, pollcb->wakeup_pipe); return APR_EINTR; } - +#else + if ((pollcb->flags & APR_POLLSET_WAKEABLE) && + pollfd->desc_type == APR_POLL_SOCKET && + pollfd->desc.s == pollcb->wakeup_socket[0]) { + apr_poll_drain_wakeup_socket(&pollcb->wakeup_set, pollcb->wakeup_socket); + return APR_EINTR; + } +#endif pollfd->rtnevents = get_revent(pollcb->pollset.ps[i].revents); rv = func(baton, pollfd); if (rv) { diff --git a/poll/unix/pollcb.c b/poll/unix/pollcb.c index 103ab9fa6..144669629 100644 --- a/poll/unix/pollcb.c +++ b/poll/unix/pollcb.c @@ -82,7 +82,11 @@ static apr_status_t pollcb_cleanup(void *p) (*pollcb->provider->cleanup)(pollcb); } if (pollcb->flags & APR_POLLSET_WAKEABLE) { +#if WAKEUP_USES_PIPE apr_poll_close_wakeup_pipe(pollcb->wakeup_pipe); +#else + apr_poll_close_wakeup_socket(pollcb->wakeup_socket); +#endif } return APR_SUCCESS; @@ -163,12 +167,21 @@ APR_DECLARE(apr_status_t) apr_pollcb_create_ex(apr_pollcb_t **ret_pollcb, } if (flags & APR_POLLSET_WAKEABLE) { +#if WAKEUP_USES_PIPE /* Create wakeup pipe */ if ((rv = apr_poll_create_wakeup_pipe(pollcb->pool, &pollcb->wakeup_pfd, - pollcb->wakeup_pipe)) - != APR_SUCCESS) { + pollcb->wakeup_pipe)) + != APR_SUCCESS) { + return rv; + } +#else + /* Create wakeup socket */ + if ((rv = apr_poll_create_wakeup_socket(pollcb->pool, &pollcb->wakeup_pfd, + pollcb->wakeup_socket)) + != APR_SUCCESS) { return rv; } +#endif if ((rv = apr_pollcb_add(pollcb, &pollcb->wakeup_pfd)) != APR_SUCCESS) { return rv; @@ -217,8 +230,14 @@ APR_DECLARE(apr_status_t) apr_pollcb_wakeup(apr_pollcb_t *pollcb) if (!(pollcb->flags & APR_POLLSET_WAKEABLE)) return APR_EINIT; - if (apr_atomic_cas32(&pollcb->wakeup_set, 1, 0) == 0) + if (apr_atomic_cas32(&pollcb->wakeup_set, 1, 0) == 0) { +#if WAKEUP_USES_PIPE return apr_file_putc(1, pollcb->wakeup_pipe[1]); +#else + apr_size_t len = 1; + return apr_socket_send(pollcb->wakeup_socket[1], "\1", &len); +#endif + } return APR_SUCCESS; } diff --git a/poll/unix/pollset.c b/poll/unix/pollset.c index 57374a5e7..6a2013637 100644 --- a/poll/unix/pollset.c +++ b/poll/unix/pollset.c @@ -38,7 +38,11 @@ static apr_status_t pollset_cleanup(void *p) (*pollset->provider->cleanup)(pollset); } if (pollset->flags & APR_POLLSET_WAKEABLE) { +#if WAKEUP_USES_PIPE apr_poll_close_wakeup_pipe(pollset->wakeup_pipe); +#else + apr_poll_close_wakeup_socket(pollset->wakeup_socket); +#endif } return APR_SUCCESS; @@ -166,13 +170,21 @@ APR_DECLARE(apr_status_t) apr_pollset_create_ex(apr_pollset_t **ret_pollset, return rv; } if (flags & APR_POLLSET_WAKEABLE) { +#if WAKEUP_USES_PIPE /* Create wakeup pipe */ if ((rv = apr_poll_create_wakeup_pipe(pollset->pool, &pollset->wakeup_pfd, pollset->wakeup_pipe)) != APR_SUCCESS) { return rv; } - +#else + /* Create wakeup socket */ + if ((rv = apr_poll_create_wakeup_socket(pollset->pool, &pollset->wakeup_pfd, + pollset->wakeup_socket)) + != APR_SUCCESS) { + return rv; + } +#endif if ((rv = apr_pollset_add(pollset, &pollset->wakeup_pfd)) != APR_SUCCESS) { return rv; } @@ -225,8 +237,14 @@ APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset) if (!(pollset->flags & APR_POLLSET_WAKEABLE)) return APR_EINIT; - if (apr_atomic_cas32(&pollset->wakeup_set, 1, 0) == 0) + if (apr_atomic_cas32(&pollset->wakeup_set, 1, 0) == 0) { +#if WAKEUP_USES_PIPE return apr_file_putc(1, pollset->wakeup_pipe[1]); +#else + apr_size_t len = 1; + return apr_socket_send(pollset->wakeup_socket[1], "\1", &len); +#endif + } return APR_SUCCESS; } diff --git a/poll/unix/select.c b/poll/unix/select.c index f2c1a1328..562ced7f6 100644 --- a/poll/unix/select.c +++ b/poll/unix/select.c @@ -248,11 +248,7 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, } else { #if !APR_FILES_AS_SOCKETS - if ((pollset->flags & APR_POLLSET_WAKEABLE) && - descriptor->desc.f == pollset->wakeup_pipe[0]) - fd = (apr_os_sock_t)descriptor->desc.f->filedes; - else - return APR_EBADF; + return APR_EBADF; #else #ifdef NETWARE /* NetWare can't handle mixed descriptor types in select() */ @@ -395,23 +391,34 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, j = 0; for (i = 0; i < pollset->nelts; i++) { apr_os_sock_t fd; - if (pollset->p->query_set[i].desc_type == APR_POLL_SOCKET) { - fd = pollset->p->query_set[i].desc.s->socketdes; - } - else { - if ((pollset->flags & APR_POLLSET_WAKEABLE) && + + if (pollset->flags & APR_POLLSET_WAKEABLE) { +#if WAKEUP_USES_PIPE + if (pollset->p->query_set[i].desc_type == APR_POLL_FILE && pollset->p->query_set[i].desc.f == pollset->wakeup_pipe[0]) { apr_poll_drain_wakeup_pipe(&pollset->wakeup_set, pollset->wakeup_pipe); rv = APR_EINTR; continue; } - else { +#else + if (pollset->p->query_set[i].desc_type == APR_POLL_SOCKET && + pollset->p->query_set[i].desc.s == pollset->wakeup_socket[0]) { + apr_poll_drain_wakeup_socket(&pollset->wakeup_set, pollset->wakeup_socket); + rv = APR_EINTR; + continue; + } +#endif + } + + if (pollset->p->query_set[i].desc_type == APR_POLL_SOCKET) { + fd = pollset->p->query_set[i].desc.s->socketdes; + } + else { #if !APR_FILES_AS_SOCKETS - return APR_EBADF; + return APR_EBADF; #else - fd = pollset->p->query_set[i].desc.f->filedes; + fd = pollset->p->query_set[i].desc.f->filedes; #endif - } } if (FD_ISSET(fd, &readset) || FD_ISSET(fd, &writeset) || FD_ISSET(fd, &exceptset)) { diff --git a/poll/unix/wakeup.c b/poll/unix/wakeup.c index b7e9efd45..bb0356444 100644 --- a/poll/unix/wakeup.c +++ b/poll/unix/wakeup.c @@ -28,34 +28,34 @@ #ifdef WIN32 -apr_status_t apr_poll_create_wakeup_pipe(apr_pool_t *pool, apr_pollfd_t *pfd, - apr_file_t **wakeup_pipe) +apr_status_t apr_poll_create_wakeup_socket(apr_pool_t *pool, apr_pollfd_t *pfd, + apr_socket_t **wakeup_socket) { apr_status_t rv; - if ((rv = apr_file_socket_pipe_create(&wakeup_pipe[0], &wakeup_pipe[1], + if ((rv = apr_socket_pipe_create(&wakeup_socket[0], &wakeup_socket[1], pool)) != APR_SUCCESS) return rv; pfd->reqevents = APR_POLLIN; - pfd->desc_type = APR_POLL_FILE; - pfd->desc.f = wakeup_pipe[0]; + pfd->desc_type = APR_POLL_SOCKET; + pfd->desc.s = wakeup_socket[0]; return APR_SUCCESS; } -apr_status_t apr_poll_close_wakeup_pipe(apr_file_t **wakeup_pipe) +apr_status_t apr_poll_close_wakeup_socket(apr_socket_t **wakeup_socket) { apr_status_t rv0 = APR_SUCCESS; apr_status_t rv1 = APR_SUCCESS; /* Close both sides of the wakeup pipe */ - if (wakeup_pipe[0]) { - rv0 = apr_file_socket_pipe_close(wakeup_pipe[0]); - wakeup_pipe[0] = NULL; + if (wakeup_socket[0]) { + rv0 = apr_socket_pipe_close(wakeup_socket[0]); + wakeup_socket[0] = NULL; } - if (wakeup_pipe[1]) { - rv1 = apr_file_socket_pipe_close(wakeup_pipe[1]); - wakeup_pipe[1] = NULL; + if (wakeup_socket[1]) { + rv1 = apr_socket_pipe_close(wakeup_socket[1]); + wakeup_socket[1] = NULL; } return rv0 ? rv0 : rv1; } @@ -134,6 +134,7 @@ apr_status_t apr_poll_close_wakeup_pipe(apr_file_t **wakeup_pipe) #endif /* APR_FILES_AS_SOCKETS */ +#if WAKEUP_USES_PIPE /* Read and discard whatever is in the wakeup pipe. */ void apr_poll_drain_wakeup_pipe(volatile apr_uint32_t *wakeup_set, apr_file_t **wakeup_pipe) @@ -143,4 +144,15 @@ void apr_poll_drain_wakeup_pipe(volatile apr_uint32_t *wakeup_set, apr_file_t ** (void)apr_file_getc(&ch, wakeup_pipe[0]); apr_atomic_set32(wakeup_set, 0); } +#else +/* Read and discard whatever is in the wakeup socket. + */ +void apr_poll_drain_wakeup_socket(volatile apr_uint32_t *wakeup_set, apr_socket_t **wakeup_socket) +{ + char ch; + apr_size_t len; + (void)apr_socket_recv(wakeup_socket[0], &ch, &len); + apr_atomic_set32(wakeup_set, 0); +} +#endif \ No newline at end of file -- cgit v1.2.1