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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "apr_arch_misc.h"
19 #include "apr_arch_threadproc.h"
20 #include "apr_arch_file_io.h"
22 #if APR_HAS_OTHER_CHILD
27 #ifdef HAVE_SYS_SELECT_H
28 #include <sys/select.h>
30 #if APR_HAVE_SYS_WAIT_H
34 #include <sys/socket.h> /* for fd_set definition! */
37 static apr_other_child_rec_t *other_children = NULL;
39 static apr_status_t other_child_cleanup(void *data)
41 apr_other_child_rec_t **pocr, *nocr;
43 for (pocr = &other_children; *pocr; pocr = &(*pocr)->next) {
44 if ((*pocr)->data == data) {
46 (*(*pocr)->maintenance) (APR_OC_REASON_UNREGISTER, (*pocr)->data, -1);
48 /* XXX: um, well we've just wasted some space in pconf ? */
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)
59 apr_other_child_rec_t *ocr;
61 ocr = apr_palloc(p, sizeof(*ocr));
64 ocr->maintenance = maintenance;
66 if (write_fd == NULL) {
67 ocr->write_fd = (apr_os_file_t) -1;
71 /* This should either go away as part of eliminating apr_proc_probe_writable_fds
72 * or write_fd should point to an apr_file_t
74 ocr->write_fd = write_fd->filehand;
76 ocr->write_fd = write_fd->filedes;
80 ocr->next = other_children;
82 apr_pool_cleanup_register(p, ocr->data, other_child_cleanup,
83 apr_pool_cleanup_null);
86 APR_DECLARE(void) apr_proc_other_child_unregister(void *data)
88 apr_other_child_rec_t *cur;
92 if (cur->data == data) {
98 /* segfault if this function called with invalid parm */
99 apr_pool_cleanup_kill(cur->p, cur->data, other_child_cleanup);
100 other_child_cleanup(data);
103 APR_DECLARE(apr_status_t) apr_proc_other_child_alert(apr_proc_t *proc,
107 apr_other_child_rec_t *ocr, *nocr;
109 for (ocr = other_children; ocr; ocr = nocr) {
111 if (ocr->proc->pid != proc->pid)
115 (*ocr->maintenance) (reason, ocr->data, status);
118 return APR_EPROC_UNKNOWN;
121 APR_DECLARE(void) apr_proc_other_child_refresh(apr_other_child_rec_t *ocr,
125 * Implement code to detect if pipes are still alive.
130 if (ocr->proc == NULL)
133 if (!ocr->proc->hproc) {
134 /* Already mopped up, perhaps we apr_proc_kill'ed it,
135 * they should have already unregistered!
138 (*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data, -1);
140 else if (!GetExitCodeProcess(ocr->proc->hproc, &status)) {
141 CloseHandle(ocr->proc->hproc);
142 ocr->proc->hproc = NULL;
144 (*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data, -1);
146 else if (status == STILL_ACTIVE) {
147 (*ocr->maintenance) (reason, ocr->data, -1);
150 CloseHandle(ocr->proc->hproc);
151 ocr->proc->hproc = NULL;
153 (*ocr->maintenance) (APR_OC_REASON_DEATH, ocr->data, status);
156 #else /* ndef Win32 */
160 if (ocr->proc == NULL)
163 waitret = waitpid(ocr->proc->pid, &status, WNOHANG);
164 if (waitret == ocr->proc->pid) {
166 (*ocr->maintenance) (APR_OC_REASON_DEATH, ocr->data, status);
168 else if (waitret == 0) {
169 (*ocr->maintenance) (reason, ocr->data, -1);
171 else if (waitret == -1) {
172 /* uh what the heck? they didn't call unregister? */
174 (*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data, -1);
179 APR_DECLARE(void) apr_proc_other_child_refresh_all(int reason)
181 apr_other_child_rec_t *ocr, *next_ocr;
183 for (ocr = other_children; ocr; ocr = next_ocr) {
184 next_ocr = ocr->next;
185 apr_proc_other_child_refresh(ocr, reason);
189 #else /* !APR_HAS_OTHER_CHILD */
191 APR_DECLARE(void) apr_proc_other_child_register(apr_proc_t *proc,
192 void (*maintenance) (int reason, void *, int status),
193 void *data, apr_file_t *write_fd, apr_pool_t *p)
198 APR_DECLARE(void) apr_proc_other_child_unregister(void *data)
203 APR_DECLARE(apr_status_t) apr_proc_other_child_alert(apr_proc_t *proc,
210 APR_DECLARE(void) apr_proc_other_child_refresh(apr_other_child_rec_t *ocr,
216 APR_DECLARE(void) apr_proc_other_child_refresh_all(int reason)
221 #endif /* APR_HAS_OTHER_CHILD */