in the situation where MaxClients is very high but
much fewer servers are actually started at the time of the
restart.
The way we notify an entire generation to die at once is
changed so that we don't have to use the pod (and deal with
the ease of filling the kernel pipe buffer).
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@93999
13f79535-47bb-0310-9956-
ffa450edef68
Changes with Apache 2.0.34-dev
+ *) Fix a hang condition with graceful restart and prefork MPM
+ in the situation where MaxClients is very high but
+ much fewer servers are actually started at the time of the
+ restart. [Jeff Trawick]
+
*) Small performance fixes for mod_include [Brian Pane]
*) Performance improvement for the error logger [Brian Pane]
ap_lingering_close(current_conn);
}
- /* Check the pod after processing a connection so that we'll go away
- * if a graceful restart occurred while we were processing the
- * connection. Otherwise, we won't wake up until a real connection
- * comes in and we'll use the wrong config to process it and we may
- * block in the wrong syscall (because the new generation is using a
- * different accept mutex) and in general it is goofy.
+ /* Check the pod and the generation number after processing a
+ * connection so that we'll go away if a graceful restart occurred
+ * while we were processing the connection or we are the lucky
+ * idle server process that gets to die.
*/
- if (!ap_mpm_pod_check(pod)) {
+ if (ap_mpm_pod_check(pod) == APR_SUCCESS) { /* selected as idle? */
+ die_now = 1;
+ }
+ else if (ap_my_generation !=
+ ap_scoreboard_image->global->running_generation) { /* restart? */
+ /* yeah, this could be non-graceful restart, in which case the
+ * parent will kill us soon enough, but why bother checking?
+ */
die_now = 1;
}
ap_sync_scoreboard_image();
int i;
apr_status_t rv = APR_SUCCESS;
+ /* we don't write anything to the pod here... we assume
+ * that the would-be reader of the pod has another way to
+ * see that it is time to die once we wake it up
+ *
+ * writing lots of things to the pod at once is very
+ * problematic... we can fill the kernel pipe buffer and
+ * be blocked until somebody consumes some bytes or
+ * we hit a timeout... if we hit a timeout we can't just
+ * keep trying because maybe we'll never successfully
+ * write again... but then maybe we'll leave would-be
+ * readers stranded (a number of them could be tied up for
+ * a while serving time-consuming requests)
+ */
for (i = 0; i < num && rv == APR_SUCCESS; i++) {
- rv = pod_signal_internal(pod);
- }
-
- if (rv == APR_SUCCESS) {
- for (i = 0; i < num && rv == APR_SUCCESS; i++) {
- rv = dummy_connection(pod);
- }
+ rv = dummy_connection(pod);
}
}
#endif /* #ifdef AP_MPM_USES_POD */