diff options
Diffstat (limited to 'server/mpm_common.c')
-rw-r--r-- | server/mpm_common.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/server/mpm_common.c b/server/mpm_common.c index 26a74891..f8063733 100644 --- a/server/mpm_common.c +++ b/server/mpm_common.c @@ -126,6 +126,11 @@ static int reclaim_one_pid(pid_t pid, action_t action) apr_proc_t proc; apr_status_t waitret; + /* Ensure pid sanity. */ + if (pid < 1) { + return 1; + } + proc.pid = pid; waitret = apr_proc_wait(&proc, NULL, NULL, APR_NOWAIT); if (waitret != APR_CHILD_NOTDONE) { @@ -305,6 +310,66 @@ void ap_relieve_child_processes(void) cur_extra = next; } } + +/* Before sending the signal to the pid this function verifies that + * the pid is a member of the current process group; either using + * apr_proc_wait(), where waitpid() guarantees to fail for non-child + * processes; or by using getpgid() directly, if available. */ +apr_status_t ap_mpm_safe_kill(pid_t pid, int sig) +{ +#ifndef HAVE_GETPGID + apr_proc_t proc; + apr_status_t rv; + apr_exit_why_e why; + int status; + + /* Ensure pid sanity */ + if (pid < 1) { + return APR_EINVAL; + } + + proc.pid = pid; + rv = apr_proc_wait(&proc, &status, &why, APR_NOWAIT); + if (rv == APR_CHILD_DONE) { +#ifdef AP_MPM_WANT_PROCESS_CHILD_STATUS + /* The child already died - log the termination status if + * necessary: */ + ap_process_child_status(&proc, why, status); +#endif + return APR_EINVAL; + } + else if (rv != APR_CHILD_NOTDONE) { + /* The child is already dead and reaped, or was a bogus pid - + * log this either way. */ + ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, ap_server_conf, + "cannot send signal %d to pid %ld (non-child or " + "already dead)", sig, (long)pid); + return APR_EINVAL; + } +#else + pid_t pg; + + /* Ensure pid sanity. */ + if (pid < 1) { + return APR_EINVAL; + } + + pg = getpgid(pid); + if (pg == -1) { + /* Process already dead... */ + return errno; + } + + if (pg != getpgrp()) { + ap_log_error(APLOG_MARK, APLOG_ALERT, 0, ap_server_conf, + "refusing to send signal %d to pid %ld outside " + "process group", sig, (long)pid); + return APR_EINVAL; + } +#endif + + return kill(pid, sig) ? errno : APR_SUCCESS; +} #endif /* AP_MPM_WANT_RECLAIM_CHILD_PROCESSES */ #ifdef AP_MPM_WANT_WAIT_OR_TIMEOUT @@ -1217,6 +1282,10 @@ apr_status_t ap_fatal_signal_setup(server_rec *s, apr_pool_t *in_pconf) if (sigaction(SIGILL, &sa, NULL) < 0) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, "sigaction(SIGILL)"); #endif +#ifdef SIGFPE + if (sigaction(SIGFPE, &sa, NULL) < 0) + ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, "sigaction(SIGFPE)"); +#endif #else /* NO_USE_SIGACTION */ @@ -1233,6 +1302,9 @@ apr_status_t ap_fatal_signal_setup(server_rec *s, apr_pool_t *in_pconf) #ifdef SIGILL apr_signal(SIGILL, sig_coredump); #endif /* SIGILL */ +#ifdef SIGFPE + apr_signal(SIGFPE, sig_coredump); +#endif /* SIGFPE */ #endif /* NO_USE_SIGACTION */ |