#if HAVE_SYS_TIME_H
#include <sys/time.h> /* for timeval definitions */
#endif
+#if HAVE_SYS_SOCKET_H
+#include <sys/socket.h> /* for setsockopt prototype */
+#endif
-#if defined(DEXTER) || defined(MPMT_BEOS_MPM) || defined(BEOS_MPM)
-#define CHILD_TABLE 1
-#define CHILD_INFO_TABLE ap_child_table
-#elif defined(MPMT_PTHREAD) || defined (NO_THREADS)
-#define SCOREBOARD 1
-#define CHILD_INFO_TABLE ap_scoreboard_image->parent
-#endif
-
-
-#ifdef CHILD_INFO_TABLE
+#ifdef MPM_NEEDS_RECLAIM_CHILD_PROCESSES
void ap_reclaim_child_processes(int terminate)
{
int i;
long int waittime = 1024 * 16; /* in usecs */
- ap_status_t waitret;
+ apr_status_t waitret;
int tries;
int not_dead_yet;
int max_daemons = ap_get_max_daemons();
-#ifdef SCOREBOARD
- ap_sync_scoreboard_image();
-#endif
+ MPM_SYNC_CHILD_TABLE();
for (tries = terminate ? 4 : 1; tries <= 9; ++tries) {
/* don't want to hold up progress any more than
* Set delay with an exponential backoff.
*/
waittime = waittime * 4;
- ap_sleep(waittime);
+ apr_sleep(waittime);
/* now see who is done */
not_dead_yet = 0;
for (i = 0; i < max_daemons; ++i) {
- pid_t pid = CHILD_INFO_TABLE[i].pid;
- ap_proc_t proc;
+ pid_t pid = MPM_CHILD_PID(i);
+ apr_proc_t proc;
-#ifdef CHILD_TABLE
- if (ap_child_table[i].status == SERVER_DEAD)
-#elif defined(SCOREBOARD)
- if (pid == ap_my_pid || pid == 0)
-#endif
+ if (pid == 0)
continue;
proc.pid = pid;
- waitret = ap_wait_proc(&proc, APR_NOWAIT);
+ waitret = apr_wait_proc(&proc, APR_NOWAIT);
if (waitret != APR_CHILD_NOTDONE) {
-#ifdef CHILD_TABLE
- ap_child_table[i].status = SERVER_DEAD;
-#elif defined(SCOREBOARD)
- ap_scoreboard_image->parent[i].pid = 0;
-#endif
+ MPM_NOTE_CHILD_KILLED(i);
continue;
}
++not_dead_yet;
break;
}
}
- ap_check_other_child();
+ apr_check_other_child();
if (!not_dead_yet) {
/* nothing left to wait for */
break;
}
}
}
-#endif
+#endif /* NEED_RECLAIM_CHILD_PROCESSES */
/* number of calls to wait_or_timeout between writable probes */
#ifndef INTERVAL_OF_WRITABLE_PROBES
#endif
static int wait_or_timeout_counter;
-void ap_wait_or_timeout(ap_wait_t *status, ap_proc_t *ret, ap_pool_t *p)
+void ap_wait_or_timeout(apr_wait_t *status, apr_proc_t *ret, apr_pool_t *p)
{
- ap_status_t rv;
+ apr_status_t rv;
++wait_or_timeout_counter;
if (wait_or_timeout_counter == INTERVAL_OF_WRITABLE_PROBES) {
wait_or_timeout_counter = 0;
-#ifdef APR_HAS_OTHER_CHILD
- ap_probe_writable_fds();
+#if APR_HAS_OTHER_CHILD
+ apr_probe_writable_fds();
#endif
}
- rv = ap_wait_all_procs(ret, status, APR_NOWAIT, p);
- if (ap_canonical_error(rv) == APR_EINTR) {
+ rv = apr_wait_all_procs(ret, status, APR_NOWAIT, p);
+ if (apr_canonical_error(rv) == APR_EINTR) {
ret->pid = -1;
return;
}
return;
}
#endif
- ap_sleep(SCOREBOARD_MAINTENANCE_INTERVAL);
+ apr_sleep(SCOREBOARD_MAINTENANCE_INTERVAL);
ret->pid = -1;
return;
}
+void ap_process_child_status(apr_proc_t *pid, apr_wait_t status)
+{
+ /* Child died... if it died due to a fatal error,
+ * we should simply bail out.
+ */
+ if ((WIFEXITED(status)) &&
+ WEXITSTATUS(status) == APEXIT_CHILDFATAL) {
+ ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, 0, ap_server_conf,
+ "Child %ld returned a Fatal error..." APR_EOL_STR
+ "Apache is exiting!",
+ (long)pid->pid);
+ exit(APEXIT_CHILDFATAL);
+ }
+ if (WIFSIGNALED(status)) {
+ switch (WTERMSIG(status)) {
+ case SIGTERM:
+ case SIGHUP:
+ case SIGUSR1:
+ case SIGKILL:
+ break;
+ default:
+#ifdef SYS_SIGLIST
+#ifdef WCOREDUMP
+ if (WCOREDUMP(status)) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
+ 0, ap_server_conf,
+ "child pid %ld exit signal %s (%d), "
+ "possible coredump in %s",
+ (long)pid->pid, (WTERMSIG(status) >= NumSIG) ? "" :
+ SYS_SIGLIST[WTERMSIG(status)], WTERMSIG(status),
+ ap_coredump_dir);
+ }
+ else {
+#endif
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
+ 0, ap_server_conf,
+ "child pid %ld exit signal %s (%d)",
+ (long)pid->pid,
+ SYS_SIGLIST[WTERMSIG(status)], WTERMSIG(status));
+#ifdef WCOREDUMP
+ }
+#endif
+#else
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
+ 0, ap_server_conf,
+ "child pid %ld exit signal %d",
+ (long)pid->pid, WTERMSIG(status));
+#endif
+ }
+ }
+}
+
+#if defined(TCP_NODELAY) && !defined(MPE) && !defined(TPF)
+void ap_sock_disable_nagle(apr_socket_t *s)
+{
+ /* The Nagle algorithm says that we should delay sending partial
+ * packets in hopes of getting more data. We don't want to do
+ * this; we are not telnet. There are bad interactions between
+ * persistent connections and Nagle's algorithm that have very severe
+ * performance penalties. (Failing to disable Nagle is not much of a
+ * problem with simple HTTP.)
+ *
+ * In spite of these problems, failure here is not a shooting offense.
+ */
+ apr_status_t status = apr_setsocketopt(s, APR_TCP_NODELAY, 1);
+ if (status != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, status, ap_server_conf,
+ "setsockopt: (TCP_NODELAY)");
+ }
+}
+#endif