From: Jeff Trawick Date: Sun, 15 May 2005 23:56:48 +0000 (+0000) Subject: Prevent hangs of child processes when writing to piped loggers at X-Git-Tag: 2.1.5~113 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f78a4e4a891444226d8972042c0a4dad2bad24d1;p=thirdparty%2Fapache%2Fhttpd.git Prevent hangs of child processes when writing to piped loggers at the time of graceful restart. PR: 26467 Reviewed by: Joe Orton git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@170281 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 4edebf661dc..660b7484b83 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ Changes with Apache 2.1.5 [Remove entries to the current 2.0 section below, when backported] + + *) Prevent hangs of child processes when writing to piped loggers at + the time of graceful restart. PR 26467. [Jeff Trawick] *) mod_info: Show the Quick Handler [Paul Querna] diff --git a/include/http_log.h b/include/http_log.h index 1e96f97b854..b6b5a7affb4 100644 --- a/include/http_log.h +++ b/include/http_log.h @@ -116,6 +116,16 @@ AP_DECLARE(apr_status_t) ap_replace_stderr_log(apr_pool_t *p, int ap_open_logs(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s_main); +/** + * 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); + /* * The primary logging functions, ap_log_error, ap_log_rerror, ap_log_cerror, * and ap_log_perror use a printf style format string to build the log message. diff --git a/server/core.c b/server/core.c index b0e14c4224b..391b09077d3 100644 --- a/server/core.c +++ b/server/core.c @@ -3755,6 +3755,7 @@ static void register_hooks(apr_pool_t *p) 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); diff --git a/server/log.c b/server/log.c index da5ecbc230e..6bcc202e76a 100644 --- a/server/log.c +++ b/server/log.c @@ -141,6 +141,45 @@ static const TRANS priorities[] = { 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); @@ -218,6 +257,9 @@ static int log_child(apr_pool_t *p, const char *progname, 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() + */ } } @@ -294,6 +336,8 @@ int ap_open_logs(apr_pool_t *pconf, apr_pool_t *p /* plog */, 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; } @@ -780,6 +824,7 @@ static int piped_log_spawn(piped_log *pl) 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];