Coverage Report

Created: 2023-03-26 06:28

/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
}