Changes with Apache 2.0.55
+ *) Prevent hangs of child processes when writing to piped loggers at
+ the time of graceful restart. PR 26467. [Jeff Trawick]
+
*) SECURITY: CAN-2005-1268 (cve.mitre.org)
mod_ssl: Fix off-by-one overflow whilst printing CRL information
at "LogLevel debug" which could be triggered if configured
int ap_open_logs(apr_pool_t *pconf, apr_pool_t *plog,
apr_pool_t *ptemp, server_rec *s_main);
+#ifdef CORE_PRIVATE
+
+/**
+ * Perform special processing for piped loggers in MPM child
+ * processes.
+ * @param p Not used
+ * @param s Not used
+ * @tip ap_logs_child_init is not for use by modules; it is an
+ * internal core function
+ */
+void ap_logs_child_init(apr_pool_t *p, server_rec *s);
+
+#endif /* CORE_PRIVATE */
+
/*
* The three primary logging functions, ap_log_error, ap_log_rerror, and
* ap_log_perror use a printf style format string to build the log message.
ap_hook_translate_name(ap_core_translate,NULL,NULL,APR_HOOK_REALLY_LAST);
ap_hook_map_to_storage(core_map_to_storage,NULL,NULL,APR_HOOK_REALLY_LAST);
ap_hook_open_logs(ap_open_logs,NULL,NULL,APR_HOOK_REALLY_FIRST);
+ ap_hook_child_init(ap_logs_child_init,NULL,NULL,APR_HOOK_MIDDLE);
ap_hook_handler(default_handler,NULL,NULL,APR_HOOK_REALLY_LAST);
/* FIXME: I suspect we can eliminate the need for these do_nothings - Ben */
ap_hook_type_checker(do_nothing,NULL,NULL,APR_HOOK_REALLY_LAST);
static apr_file_t *stderr_log = NULL;
+/* track pipe handles to close in child process */
+typedef struct read_handle_t {
+ struct read_handle_t *next;
+ apr_file_t *handle;
+} read_handle_t;
+
+static read_handle_t *read_handles;
+
+/* clear_handle_list() is called when plog is cleared; at that
+ * point we need to forget about our old list of pipe read
+ * handles
+ */
+static apr_status_t clear_handle_list(void *v)
+{
+ read_handles = NULL;
+ return APR_SUCCESS;
+}
+
+/* remember to close this handle in the child process */
+static void close_handle_in_child(apr_pool_t *p, apr_file_t *f)
+{
+ read_handle_t *new_handle;
+
+ new_handle = apr_pcalloc(p, sizeof(read_handle_t));
+ new_handle->next = read_handles;
+ new_handle->handle = f;
+ read_handles = new_handle;
+}
+
+void ap_logs_child_init(apr_pool_t *p, server_rec *s)
+{
+ read_handle_t *cur = read_handles;
+
+ while (cur) {
+ apr_file_close(cur->handle);
+ cur = cur->next;
+ }
+}
+
AP_DECLARE(void) ap_open_stderr_log(apr_pool_t *p)
{
apr_file_open_stderr(&stderr_log, p);
if (rc == APR_SUCCESS) {
apr_pool_note_subprocess(p, procnew, APR_KILL_AFTER_TIMEOUT);
(*fpin) = procnew->in;
+ /* read handle to pipe not kept open, so no need to call
+ * close_handle_in_child()
+ */
}
}
int replace_stderr;
apr_file_t *errfile = NULL;
+ apr_pool_cleanup_register(p, NULL, clear_handle_list,
+ apr_pool_cleanup_null);
if (open_error_log(s_main, p) != OK) {
return DONE;
}
ap_piped_log_write_fd(pl) = procnew->in;
apr_proc_other_child_register(procnew, piped_log_maintenance, pl,
ap_piped_log_write_fd(pl), pl->p);
+ close_handle_in_child(pl->p, ap_piped_log_read_fd(pl));
}
else {
char buf[120];