Coverage Report

Created: 2026-09-06 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/httpd/srclib/apr/misc/unix/otherchild.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.h"
18
#include "apr_arch_misc.h"
19
#include "apr_arch_threadproc.h"
20
#include "apr_arch_file_io.h"
21
22
#if APR_HAS_OTHER_CHILD
23
24
#ifdef HAVE_TIME_H
25
#include <sys/time.h>
26
#endif
27
#ifdef HAVE_SYS_SELECT_H
28
#include <sys/select.h>
29
#endif
30
#if APR_HAVE_SYS_WAIT_H
31
#include <sys/wait.h>
32
#endif
33
34
static apr_other_child_rec_t *other_children = NULL;
35
36
static apr_status_t other_child_cleanup(void *data)
37
0
{
38
0
    apr_other_child_rec_t **pocr, *nocr;
39
40
0
    for (pocr = &other_children; *pocr; pocr = &(*pocr)->next) {
41
0
        if ((*pocr)->data == data) {
42
0
            nocr = (*pocr)->next;
43
0
            (*(*pocr)->maintenance) (APR_OC_REASON_UNREGISTER, (*pocr)->data, -1);
44
0
            *pocr = nocr;
45
            /* XXX: um, well we've just wasted some space in pconf ? */
46
0
            return APR_SUCCESS;
47
0
        }
48
0
    }
49
0
    return APR_SUCCESS;
50
0
}
51
52
APR_DECLARE(void) apr_proc_other_child_register(apr_proc_t *proc,
53
                     void (*maintenance) (int reason, void *, int status),
54
                     void *data, apr_file_t *write_fd, apr_pool_t *p)
55
0
{
56
0
    apr_other_child_rec_t *ocr;
57
58
0
    ocr = apr_palloc(p, sizeof(*ocr));
59
0
    ocr->p = p;
60
0
    ocr->proc = proc;
61
0
    ocr->maintenance = maintenance;
62
0
    ocr->data = data;
63
0
    ocr->next = other_children;
64
0
    other_children = ocr;
65
0
    apr_pool_cleanup_register(p, ocr->data, other_child_cleanup,
66
0
                              apr_pool_cleanup_null);
67
0
}
68
69
APR_DECLARE(void) apr_proc_other_child_unregister(void *data)
70
0
{
71
0
    apr_other_child_rec_t *cur;
72
73
0
    cur = other_children;
74
0
    while (cur) {
75
0
        if (cur->data == data) {
76
0
            break;
77
0
        }
78
0
        cur = cur->next;
79
0
    }
80
81
    /* segfault if this function called with invalid parm */
82
0
    apr_pool_cleanup_kill(cur->p, cur->data, other_child_cleanup);
83
0
    other_child_cleanup(data);
84
0
}
85
86
APR_DECLARE(apr_status_t) apr_proc_other_child_alert(apr_proc_t *proc,
87
                                                     int reason,
88
                                                     int status)
89
0
{
90
0
    apr_other_child_rec_t *ocr, *nocr;
91
92
0
    for (ocr = other_children; ocr; ocr = nocr) {
93
0
        nocr = ocr->next;
94
0
        if (ocr->proc->pid != proc->pid)
95
0
            continue;
96
97
0
        ocr->proc = NULL;
98
0
        (*ocr->maintenance) (reason, ocr->data, status);
99
0
        return APR_SUCCESS;
100
0
    }
101
0
    return APR_EPROC_UNKNOWN;
102
0
}
103
104
APR_DECLARE(void) apr_proc_other_child_refresh(apr_other_child_rec_t *ocr,
105
                                               int reason)
106
0
{
107
    /* Todo:
108
     * Implement code to detect if pipes are still alive.
109
     */
110
#ifdef WIN32
111
    DWORD status;
112
113
    if (ocr->proc == NULL)
114
        return;
115
116
    if (!ocr->proc->hproc) {
117
        /* Already mopped up, perhaps we apr_proc_kill'ed it,
118
         * they should have already unregistered!
119
         */
120
        ocr->proc = NULL;
121
        (*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data, -1);
122
    }
123
    else if (!GetExitCodeProcess(ocr->proc->hproc, &status)) {
124
        CloseHandle(ocr->proc->hproc);
125
        ocr->proc->hproc = NULL;
126
        ocr->proc = NULL;
127
        (*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data, -1);
128
    }
129
    else if (status == STILL_ACTIVE) {
130
        (*ocr->maintenance) (reason, ocr->data, -1);
131
    }
132
    else {
133
        CloseHandle(ocr->proc->hproc);
134
        ocr->proc->hproc = NULL;
135
        ocr->proc = NULL;
136
        (*ocr->maintenance) (APR_OC_REASON_DEATH, ocr->data, status);
137
    }
138
139
#elif defined(OS2)
140
    int rc;
141
    int status;
142
    RESULTCODES proc_rc;
143
    PID ended_pid;
144
145
    if (ocr->proc == NULL) {
146
        return;
147
    }
148
149
    rc = DosWaitChild(DCWA_PROCESS, DCWW_NOWAIT, &proc_rc, &ended_pid, ocr->proc->pid);
150
151
    switch (rc) {
152
    case 0:
153
        ocr->proc = NULL;
154
        status = (proc_rc.codeResult << 8) | proc_rc.codeTerminate;
155
        (*ocr->maintenance) (APR_OC_REASON_DEATH, ocr->data, status);
156
        break;
157
158
    case ERROR_CHILD_NOT_COMPLETE:
159
        (*ocr->maintenance) (reason, ocr->data, -1);
160
        break;
161
162
    default:
163
        ocr->proc = NULL;
164
        (*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data, -1);
165
        break;
166
    }
167
#else /* ndef Win32 */
168
0
    pid_t waitret;
169
0
    int status;
170
171
0
    if (ocr->proc == NULL)
172
0
        return;
173
174
0
    waitret = waitpid(ocr->proc->pid, &status, WNOHANG);
175
0
    if (waitret == ocr->proc->pid) {
176
0
        ocr->proc = NULL;
177
0
        (*ocr->maintenance) (APR_OC_REASON_DEATH, ocr->data, status);
178
0
    }
179
0
    else if (waitret == 0) {
180
0
        (*ocr->maintenance) (reason, ocr->data, -1);
181
0
    }
182
0
    else if (waitret == -1) {
183
        /* uh what the heck? they didn't call unregister? */
184
0
        ocr->proc = NULL;
185
0
        (*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data, -1);
186
0
    }
187
0
#endif
188
0
}
189
190
APR_DECLARE(void) apr_proc_other_child_refresh_all(int reason)
191
0
{
192
0
    apr_other_child_rec_t *ocr, *next_ocr;
193
194
0
    for (ocr = other_children; ocr; ocr = next_ocr) {
195
0
        next_ocr = ocr->next;
196
0
        apr_proc_other_child_refresh(ocr, reason);
197
0
    }
198
0
}
199
200
#else /* !APR_HAS_OTHER_CHILD */
201
202
APR_DECLARE(void) apr_proc_other_child_register(apr_proc_t *proc,
203
                     void (*maintenance) (int reason, void *, int status),
204
                     void *data, apr_file_t *write_fd, apr_pool_t *p)
205
{
206
    return;
207
}
208
209
APR_DECLARE(void) apr_proc_other_child_unregister(void *data)
210
{
211
    return;
212
}
213
214
APR_DECLARE(apr_status_t) apr_proc_other_child_alert(apr_proc_t *proc,
215
                                                     int reason,
216
                                                     int status)
217
{
218
    return APR_ENOTIMPL;
219
}
220
221
APR_DECLARE(void) apr_proc_other_child_refresh(apr_other_child_rec_t *ocr,
222
                                               int reason)
223
{
224
    return;
225
}
226
227
APR_DECLARE(void) apr_proc_other_child_refresh_all(int reason)
228
{
229
    return;
230
}
231
232
#endif /* APR_HAS_OTHER_CHILD */