Coverage Report

Created: 2025-11-24 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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 */