/src/httpd/srclib/apr/poll/unix/pollset.c
Line | Count | Source (jump to first uncovered line) |
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 | | #ifdef WIN32 |
18 | | /* POSIX defines 1024 for the FD_SETSIZE */ |
19 | | #define FD_SETSIZE 1024 |
20 | | #endif |
21 | | |
22 | | #include "apr.h" |
23 | | #include "apr_poll.h" |
24 | | #include "apr_time.h" |
25 | | #include "apr_portable.h" |
26 | | #include "apr_atomic.h" |
27 | | #include "apr_arch_file_io.h" |
28 | | #include "apr_arch_networkio.h" |
29 | | #include "apr_arch_poll_private.h" |
30 | | #include "apr_arch_inherit.h" |
31 | | |
32 | | static apr_pollset_method_e pollset_default_method = POLLSET_DEFAULT_METHOD; |
33 | | |
34 | | static apr_status_t pollset_cleanup(void *p) |
35 | 0 | { |
36 | 0 | apr_pollset_t *pollset = (apr_pollset_t *) p; |
37 | 0 | if (pollset->provider->cleanup) { |
38 | 0 | (*pollset->provider->cleanup)(pollset); |
39 | 0 | } |
40 | 0 | if (pollset->flags & APR_POLLSET_WAKEABLE) { |
41 | 0 | #if WAKEUP_USES_PIPE |
42 | 0 | apr_poll_close_wakeup_pipe(pollset->wakeup_pipe); |
43 | | #else |
44 | | apr_poll_close_wakeup_socket(pollset->wakeup_socket); |
45 | | #endif |
46 | 0 | } |
47 | |
|
48 | 0 | return APR_SUCCESS; |
49 | 0 | } |
50 | | |
51 | | #if defined(HAVE_KQUEUE) |
52 | | extern const apr_pollset_provider_t *apr_pollset_provider_kqueue; |
53 | | #endif |
54 | | #if defined(HAVE_PORT_CREATE) |
55 | | extern const apr_pollset_provider_t *apr_pollset_provider_port; |
56 | | #endif |
57 | | #if defined(HAVE_EPOLL) |
58 | | extern const apr_pollset_provider_t *apr_pollset_provider_epoll; |
59 | | #endif |
60 | | #if defined(HAVE_AIO_MSGQ) |
61 | | extern const apr_pollset_provider_t *apr_pollset_provider_aio_msgq; |
62 | | #endif |
63 | | #if defined(HAVE_POLL) |
64 | | extern const apr_pollset_provider_t *apr_pollset_provider_poll; |
65 | | #endif |
66 | | extern const apr_pollset_provider_t *apr_pollset_provider_select; |
67 | | |
68 | | static const apr_pollset_provider_t *pollset_provider(apr_pollset_method_e method) |
69 | 0 | { |
70 | 0 | const apr_pollset_provider_t *provider = NULL; |
71 | 0 | switch (method) { |
72 | 0 | case APR_POLLSET_KQUEUE: |
73 | | #if defined(HAVE_KQUEUE) |
74 | | provider = apr_pollset_provider_kqueue; |
75 | | #endif |
76 | 0 | break; |
77 | 0 | case APR_POLLSET_PORT: |
78 | | #if defined(HAVE_PORT_CREATE) |
79 | | provider = apr_pollset_provider_port; |
80 | | #endif |
81 | 0 | break; |
82 | 0 | case APR_POLLSET_EPOLL: |
83 | 0 | #if defined(HAVE_EPOLL) |
84 | 0 | provider = apr_pollset_provider_epoll; |
85 | 0 | #endif |
86 | 0 | break; |
87 | 0 | case APR_POLLSET_AIO_MSGQ: |
88 | | #if defined(HAVE_AIO_MSGQ) |
89 | | provider = apr_pollset_provider_aio_msgq; |
90 | | #endif |
91 | 0 | break; |
92 | 0 | case APR_POLLSET_POLL: |
93 | 0 | #if defined(HAVE_POLL) |
94 | 0 | provider = apr_pollset_provider_poll; |
95 | 0 | #endif |
96 | 0 | break; |
97 | 0 | case APR_POLLSET_SELECT: |
98 | 0 | provider = apr_pollset_provider_select; |
99 | 0 | break; |
100 | 0 | case APR_POLLSET_DEFAULT: |
101 | 0 | break; |
102 | 0 | } |
103 | 0 | return provider; |
104 | 0 | } |
105 | | |
106 | | APR_DECLARE(apr_status_t) apr_pollset_create_ex(apr_pollset_t **ret_pollset, |
107 | | apr_uint32_t size, |
108 | | apr_pool_t *p, |
109 | | apr_uint32_t flags, |
110 | | apr_pollset_method_e method) |
111 | 0 | { |
112 | 0 | apr_status_t rv; |
113 | 0 | apr_pollset_t *pollset; |
114 | 0 | const apr_pollset_provider_t *provider = NULL; |
115 | |
|
116 | 0 | *ret_pollset = NULL; |
117 | |
|
118 | | #ifdef WIN32 |
119 | | /* Favor WSAPoll. */ |
120 | | if (method == APR_POLLSET_DEFAULT) { |
121 | | method = APR_POLLSET_POLL; |
122 | | } |
123 | | #endif |
124 | |
|
125 | 0 | if (method == APR_POLLSET_DEFAULT) |
126 | 0 | method = pollset_default_method; |
127 | 0 | while (provider == NULL) { |
128 | 0 | provider = pollset_provider(method); |
129 | 0 | if (!provider) { |
130 | 0 | if ((flags & APR_POLLSET_NODEFAULT) == APR_POLLSET_NODEFAULT) |
131 | 0 | return APR_ENOTIMPL; |
132 | 0 | if (method == pollset_default_method) |
133 | 0 | return APR_ENOTIMPL; |
134 | 0 | method = pollset_default_method; |
135 | 0 | } |
136 | 0 | } |
137 | 0 | if (flags & APR_POLLSET_WAKEABLE) { |
138 | | /* Add room for wakeup descriptor */ |
139 | 0 | size++; |
140 | 0 | } |
141 | |
|
142 | 0 | pollset = apr_palloc(p, sizeof(*pollset)); |
143 | 0 | pollset->nelts = 0; |
144 | 0 | pollset->nalloc = size; |
145 | 0 | pollset->pool = p; |
146 | 0 | pollset->flags = flags; |
147 | 0 | pollset->provider = provider; |
148 | 0 | pollset->wakeup_set = 0; |
149 | |
|
150 | 0 | rv = (*provider->create)(pollset, size, p, flags); |
151 | 0 | if (rv == APR_ENOTIMPL) { |
152 | 0 | if (method == pollset_default_method) { |
153 | 0 | return rv; |
154 | 0 | } |
155 | 0 | provider = pollset_provider(pollset_default_method); |
156 | 0 | if (!provider) { |
157 | 0 | return APR_ENOTIMPL; |
158 | 0 | } |
159 | 0 | rv = (*provider->create)(pollset, size, p, flags); |
160 | 0 | if (rv != APR_SUCCESS) { |
161 | 0 | return rv; |
162 | 0 | } |
163 | 0 | pollset->provider = provider; |
164 | 0 | } |
165 | 0 | else if (rv != APR_SUCCESS) { |
166 | 0 | return rv; |
167 | 0 | } |
168 | 0 | if (flags & APR_POLLSET_WAKEABLE) { |
169 | 0 | #if WAKEUP_USES_PIPE |
170 | | /* Create wakeup pipe */ |
171 | 0 | if ((rv = apr_poll_create_wakeup_pipe(pollset->pool, &pollset->wakeup_pfd, |
172 | 0 | pollset->wakeup_pipe)) |
173 | 0 | != APR_SUCCESS) { |
174 | 0 | return rv; |
175 | 0 | } |
176 | | #else |
177 | | /* Create wakeup socket */ |
178 | | if ((rv = apr_poll_create_wakeup_socket(pollset->pool, &pollset->wakeup_pfd, |
179 | | pollset->wakeup_socket)) |
180 | | != APR_SUCCESS) { |
181 | | return rv; |
182 | | } |
183 | | #endif |
184 | 0 | if ((rv = apr_pollset_add(pollset, &pollset->wakeup_pfd)) != APR_SUCCESS) { |
185 | 0 | return rv; |
186 | 0 | } |
187 | 0 | } |
188 | 0 | if ((flags & APR_POLLSET_WAKEABLE) || provider->cleanup) |
189 | 0 | apr_pool_cleanup_register(p, pollset, pollset_cleanup, |
190 | 0 | apr_pool_cleanup_null); |
191 | |
|
192 | 0 | *ret_pollset = pollset; |
193 | 0 | return APR_SUCCESS; |
194 | 0 | } |
195 | | |
196 | | APR_DECLARE(const char *) apr_pollset_method_name(apr_pollset_t *pollset) |
197 | 0 | { |
198 | 0 | return pollset->provider->name; |
199 | 0 | } |
200 | | |
201 | | APR_DECLARE(const char *) apr_poll_method_defname(void) |
202 | 0 | { |
203 | 0 | const apr_pollset_provider_t *provider = NULL; |
204 | |
|
205 | 0 | provider = pollset_provider(pollset_default_method); |
206 | 0 | if (provider) |
207 | 0 | return provider->name; |
208 | 0 | else |
209 | 0 | return "unknown"; |
210 | 0 | } |
211 | | |
212 | | APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, |
213 | | apr_uint32_t size, |
214 | | apr_pool_t *p, |
215 | | apr_uint32_t flags) |
216 | 0 | { |
217 | 0 | apr_pollset_method_e method = APR_POLLSET_DEFAULT; |
218 | 0 | return apr_pollset_create_ex(pollset, size, p, flags, method); |
219 | 0 | } |
220 | | |
221 | | APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t * pollset) |
222 | 0 | { |
223 | 0 | if (pollset->flags & APR_POLLSET_WAKEABLE || |
224 | 0 | pollset->provider->cleanup) |
225 | 0 | return apr_pool_cleanup_run(pollset->pool, pollset, |
226 | 0 | pollset_cleanup); |
227 | 0 | else |
228 | 0 | return APR_SUCCESS; |
229 | 0 | } |
230 | | |
231 | | APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset) |
232 | 0 | { |
233 | 0 | if (!(pollset->flags & APR_POLLSET_WAKEABLE)) |
234 | 0 | return APR_EINIT; |
235 | | |
236 | 0 | if (apr_atomic_cas32(&pollset->wakeup_set, 1, 0) == 0) { |
237 | 0 | #if WAKEUP_USES_PIPE |
238 | 0 | return apr_file_putc(1, pollset->wakeup_pipe[1]); |
239 | | #else |
240 | | apr_size_t len = 1; |
241 | | return apr_socket_send(pollset->wakeup_socket[1], "\1", &len); |
242 | | #endif |
243 | 0 | } |
244 | | |
245 | 0 | return APR_SUCCESS; |
246 | 0 | } |
247 | | |
248 | | APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, |
249 | | const apr_pollfd_t *descriptor) |
250 | 0 | { |
251 | 0 | return (*pollset->provider->add)(pollset, descriptor); |
252 | 0 | } |
253 | | |
254 | | APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, |
255 | | const apr_pollfd_t *descriptor) |
256 | 0 | { |
257 | 0 | return (*pollset->provider->remove)(pollset, descriptor); |
258 | 0 | } |
259 | | |
260 | | APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, |
261 | | apr_interval_time_t timeout, |
262 | | apr_int32_t *num, |
263 | | const apr_pollfd_t **descriptors) |
264 | 0 | { |
265 | 0 | return (*pollset->provider->poll)(pollset, timeout, num, descriptors); |
266 | 0 | } |