Coverage Report

Created: 2023-03-26 06:28

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