Continuing with my example of
/**
* Check on the specified process. If it is gone, call the maintenance
* function.
* @param pid The process to check.
* @param status The status to pass to the maintenance function.
*/
APR_DECLARE(apr_status_t) apr_proc_other_child_read(apr_proc_t *pid, int
status);
we have this code on Unix...
APR_DECLARE(apr_status_t) apr_proc_other_child_read(apr_proc_t *pid, int status)
{
apr_other_child_rec_t *ocr, *nocr;
for (ocr = other_children; ocr; ocr = nocr) {
nocr = ocr->next;
if (ocr->proc->pid != pid->pid)
continue;
ocr->proc = NULL;
(*ocr->maintenance) (APR_OC_REASON_DEATH, ocr->data, status);
return 0;
}
return APR_CHILD_NOTDONE;
}
So let's look at the use case (chopped down from the prefork MPM);
int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
{
[...]
restart_pending = shutdown_pending = 0;
while (!restart_pending && !shutdown_pending) {
apr_exit_why_e exitwhy;
int status, processed_status;
apr_proc_t pid;
ap_wait_or_timeout(&exitwhy, &status, &pid, pconf);
if (pid.pid != -1) {
processed_status = ap_process_child_status(&pid, exitwhy, status);
if (processed_status == APEXIT_CHILDFATAL) {
return 1;
}
/* non-fatal death... note that it's gone in the scoreboard. */
child_slot = find_child_by_pid(&pid);
if (child_slot >= 0) {
[...]
#if APR_HAS_OTHER_CHILD
}
else if (apr_proc_other_child_read(&pid, status) == 0) {
/* handled */
#endif
}
[...]
continue;
[...]
}
perform_idle_server_maintenance(pconf);
[...]
}
}
Now how is apr_proc_other_child_read related to its description above? There
is no check
for the current health of the process. apr_proc_other_child_read appears to
really be
apr_proc_other_child_died(), a function we can't support on win32. Why not?
Because we
don't have 'child processes' that raise exceptions. Yes - we can have them
raise an event,
add them to a poll that signals when the process exits (if we have the
apr_proc_t we created
when we spawned the child - that apr_proc_t contains a handle that can be
sampled.)
Bill