summaryrefslogtreecommitdiff
path: root/server/mpm_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/mpm_common.c')
-rw-r--r--server/mpm_common.c72
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 */