1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "apr_arch_file_io.h" 18#include "apr_arch_networkio.h" 19#include "apr_poll.h" 20#include "apr_errno.h" 21#include "apr_support.h" 22 23/* The only case where we don't use wait_for_io_or_timeout is on 24 * pre-BONE BeOS, so this check should be sufficient and simpler */ 25#if !defined(BEOS_R5) && !defined(OS2) && APR_FILES_AS_SOCKETS 26#define USE_WAIT_FOR_IO 27#endif 28 29#ifdef USE_WAIT_FOR_IO 30 31#ifdef WAITIO_USES_POLL 32 33#ifdef HAVE_POLL_H 34#include <poll.h> 35#endif 36#ifdef HAVE_SYS_POLL_H 37#include <sys/poll.h> 38#endif 39 40apr_status_t apr_wait_for_io_or_timeout(apr_file_t *f, apr_socket_t *s, 41 int for_read) 42{ 43 struct pollfd pfd; 44 int rc, timeout; 45 46 timeout = f ? f->timeout / 1000 : s->timeout / 1000; 47 pfd.fd = f ? f->filedes : s->socketdes; 48 pfd.events = for_read ? POLLIN : POLLOUT; 49 50 do { 51 rc = poll(&pfd, 1, timeout); 52 } while (rc == -1 && errno == EINTR); 53 if (rc == 0) { 54 return APR_TIMEUP; 55 } 56 else if (rc > 0) { 57 return APR_SUCCESS; 58 } 59 else { 60 return errno; 61 } 62} 63 64#else /* !WAITIO_USES_POLL */ 65 66apr_status_t apr_wait_for_io_or_timeout(apr_file_t *f, apr_socket_t *s, 67 int for_read) 68{ 69 apr_interval_time_t timeout; 70 apr_pollfd_t pfd; 71 int type = for_read ? APR_POLLIN : APR_POLLOUT; 72 apr_pollset_t *pollset; 73 apr_status_t status; 74 75 /* TODO - timeout should be less each time through this loop */ 76 if (f) { 77 pfd.desc_type = APR_POLL_FILE; 78 pfd.desc.f = f; 79 80 pollset = f->pollset; 81 if (pollset == NULL) { 82 status = apr_pollset_create(&(f->pollset), 1, f->pool, 0); 83 if (status != APR_SUCCESS) { 84 return status; 85 } 86 pollset = f->pollset; 87 } 88 timeout = f->timeout; 89 } 90 else { 91 pfd.desc_type = APR_POLL_SOCKET; 92 pfd.desc.s = s; 93 94 pollset = s->pollset; 95 timeout = s->timeout; 96 } 97 pfd.reqevents = type; 98 99 /* Remove the object if it was in the pollset, then add in the new 100 * object with the correct reqevents value. Ignore the status result 101 * on the remove, because it might not be in there (yet). 102 */ 103 (void) apr_pollset_remove(pollset, &pfd); 104 105 /* ### check status code */ 106 (void) apr_pollset_add(pollset, &pfd); 107 108 do { 109 int numdesc; 110 const apr_pollfd_t *pdesc; 111 112 status = apr_pollset_poll(pollset, timeout, &numdesc, &pdesc); 113 114 if (numdesc == 1 && (pdesc[0].rtnevents & type) != 0) { 115 return APR_SUCCESS; 116 } 117 } while (APR_STATUS_IS_EINTR(status)); 118 119 return status; 120} 121#endif /* WAITIO_USES_POLL */ 122 123#endif /* USE_WAIT_FOR_IO */ 124