/src/httpd/srclib/apr/support/unix/waitio.c
Line | Count | Source |
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 | | #if HAVE_POLL_H |
34 | | #include <poll.h> |
35 | | #elif HAVE_SYS_POLL_H |
36 | | #include <sys/poll.h> |
37 | | #endif |
38 | | |
39 | | apr_status_t apr_wait_for_io_or_timeout(apr_file_t *f, apr_socket_t *s, |
40 | | int for_read) |
41 | 0 | { |
42 | 0 | struct pollfd pfd; |
43 | 0 | apr_interval_time_t raw_timeout; |
44 | 0 | int rc, timeout; |
45 | |
|
46 | 0 | raw_timeout = f ? f->timeout : s->timeout; |
47 | 0 | if (raw_timeout > ((apr_interval_time_t)INT_MAX) * 1000) { |
48 | | /* timeout value exceeds maximum allowed (~25 days in microseconds) |
49 | | * capping to INT_MAX milliseconds to avoid overflow */ |
50 | 0 | timeout = INT_MAX; |
51 | 0 | } else { |
52 | | /* convert microseconds to milliseconds (round up) */ |
53 | 0 | timeout = raw_timeout > 0 ? (int)((raw_timeout + 999) / 1000) : (int)raw_timeout; |
54 | 0 | } |
55 | |
|
56 | 0 | pfd.fd = f ? f->filedes : s->socketdes; |
57 | 0 | pfd.events = for_read ? POLLIN : POLLOUT; |
58 | |
|
59 | 0 | do { |
60 | 0 | rc = poll(&pfd, 1, timeout); |
61 | 0 | } while (rc == -1 && errno == EINTR); |
62 | 0 | if (rc == 0) { |
63 | 0 | return APR_TIMEUP; |
64 | 0 | } |
65 | 0 | else if (rc > 0) { |
66 | 0 | return APR_SUCCESS; |
67 | 0 | } |
68 | 0 | else { |
69 | | return errno; |
70 | 0 | } |
71 | 0 | } |
72 | | |
73 | | #else /* !WAITIO_USES_POLL */ |
74 | | |
75 | | apr_status_t apr_wait_for_io_or_timeout(apr_file_t *f, apr_socket_t *s, |
76 | | int for_read) |
77 | | { |
78 | | apr_interval_time_t timeout; |
79 | | apr_pollfd_t pfd; |
80 | | int type = for_read ? APR_POLLIN : APR_POLLOUT; |
81 | | apr_pollset_t *pollset; |
82 | | apr_status_t status; |
83 | | |
84 | | /* TODO - timeout should be less each time through this loop */ |
85 | | if (f) { |
86 | | pfd.desc_type = APR_POLL_FILE; |
87 | | pfd.desc.f = f; |
88 | | |
89 | | pollset = f->pollset; |
90 | | if (pollset == NULL) { |
91 | | status = apr_pollset_create(&(f->pollset), 1, f->pool, 0); |
92 | | if (status != APR_SUCCESS) { |
93 | | return status; |
94 | | } |
95 | | pollset = f->pollset; |
96 | | } |
97 | | timeout = f->timeout; |
98 | | } |
99 | | else { |
100 | | pfd.desc_type = APR_POLL_SOCKET; |
101 | | pfd.desc.s = s; |
102 | | |
103 | | pollset = s->pollset; |
104 | | timeout = s->timeout; |
105 | | } |
106 | | pfd.reqevents = type; |
107 | | |
108 | | /* Remove the object if it was in the pollset, then add in the new |
109 | | * object with the correct reqevents value. Ignore the status result |
110 | | * on the remove, because it might not be in there (yet). |
111 | | */ |
112 | | (void) apr_pollset_remove(pollset, &pfd); |
113 | | |
114 | | /* ### check status code */ |
115 | | (void) apr_pollset_add(pollset, &pfd); |
116 | | |
117 | | do { |
118 | | int numdesc; |
119 | | const apr_pollfd_t *pdesc; |
120 | | |
121 | | status = apr_pollset_poll(pollset, timeout, &numdesc, &pdesc); |
122 | | |
123 | | if (numdesc == 1 && (pdesc[0].rtnevents & type) != 0) { |
124 | | return APR_SUCCESS; |
125 | | } |
126 | | } while (APR_STATUS_IS_EINTR(status)); |
127 | | |
128 | | return status; |
129 | | } |
130 | | #endif /* WAITIO_USES_POLL */ |
131 | | |
132 | | #endif /* USE_WAIT_FOR_IO */ |