Author: rjung Date: Tue Jan 6 03:12:30 2015 New Revision: 1649728 URL: http://svn.apache.org/r1649728 Log: Further improve handling of piped loggers during graceful or normal restart.
Some "Broken Pipe" errors in children mod_jk logging remain when doing graceful restart under load. This is because rotatelogs gets restarted very early during graceful restart and the pool cleanups in the children do not run for some time, so remaining requests log to the closed pipe. Modified: tomcat/jk/trunk/native/apache-1.3/mod_jk.c tomcat/jk/trunk/native/apache-2.0/mod_jk.c tomcat/jk/trunk/native/common/jk_logger.h Modified: tomcat/jk/trunk/native/apache-1.3/mod_jk.c URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/apache-1.3/mod_jk.c?rev=1649728&r1=1649727&r2=1649728&view=diff ============================================================================== --- tomcat/jk/trunk/native/apache-1.3/mod_jk.c (original) +++ tomcat/jk/trunk/native/apache-1.3/mod_jk.c Tue Jan 6 03:12:30 2015 @@ -137,7 +137,6 @@ typedef struct * Log stuff */ char *log_file; - int log_fd; int log_level; jk_logger_t *log; @@ -265,7 +264,6 @@ typedef struct dir_config_struct static server_rec *main_server = NULL; static jk_logger_t *main_log = NULL; -static int main_log_is_piped = JK_FALSE; static table *jk_log_fds = NULL; static jk_worker_env_t worker_env; static char *jk_shm_file = NULL; @@ -2778,7 +2776,6 @@ static void *create_jk_config(ap_pool * jk_server_conf_t *c = (jk_server_conf_t *) ap_pcalloc(p, sizeof(jk_server_conf_t)); - c->log_fd = -1; c->mountcopy = JK_FALSE; c->was_initialized = JK_FALSE; @@ -3012,7 +3009,6 @@ static void open_jk_log(server_rec *s, p const char *fname; int jklogfd; piped_log *pl; - int is_piped = JK_FALSE; jk_logger_t *jkl; jk_file_logger_t *flp; jk_server_conf_t *conf = @@ -3054,7 +3050,6 @@ static void open_jk_log(server_rec *s, p exit(1); } jklogfd = ap_piped_log_write_fd(pl); - is_piped = JK_TRUE; } else { fname = ap_server_root_relative(p, conf->log_file); @@ -3077,19 +3072,21 @@ static void open_jk_log(server_rec *s, p } log_fd_set(p, conf->log_file, jklogfd); } - conf->log_fd = jklogfd; jkl = (jk_logger_t *)ap_palloc(p, sizeof(jk_logger_t)); flp = (jk_file_logger_t *)ap_palloc(p, sizeof(jk_file_logger_t)); if (jkl && flp) { jkl->log = jk_log_to_file; jkl->level = conf->log_level; jkl->logger_private = flp; - flp->log_fd = conf->log_fd; + flp->log_fd = jklogfd; + if (*conf->log_file == '|') + flp->is_piped = JK_TRUE; + else + flp->is_piped = JK_FALSE; conf->log = jkl; jk_set_time_fmt(conf->log, conf->stamp_format_string); if (main_log == NULL) main_log = conf->log; - main_log_is_piped = is_piped; return; } @@ -3550,10 +3547,27 @@ static int jk_fixups(request_rec * r) static void child_exit_handler(server_rec * s, ap_pool * p) { - wc_shutdown(main_log); + /* If the main log is piped, we need to make sure + * it is no longer used. The external log process + * (e.g. rotatelogs) will be gone now and the pipe will + * block, once the buffer gets full. Setting + * log_fd to -1 makes logging switch to error log. + */ + jk_server_conf_t *conf = + (jk_server_conf_t *) ap_get_module_config(s->module_config, + &jk_module); + jk_logger_t *l = conf->log; + if (l && l->logger_private) { + jk_file_logger_t *p = l->logger_private; + if (p && p->is_piped == JK_TRUE) { + p->log_fd = -1; + p->is_piped = JK_FALSE; + } + } + wc_shutdown(l); /* srevilak - refactor cleanup body to jk_generic_cleanup() */ jk_generic_cleanup(s); - jk_shm_close(main_log); + jk_shm_close(l); } static void child_init_handler(server_rec * s, ap_pool * p) @@ -3578,8 +3592,26 @@ static void child_init_handler(server_re /** srevilak -- registered as a cleanup handler in jk_init */ static void jk_server_cleanup(void *data) { - jk_generic_cleanup((server_rec *) data); - jk_shm_close(main_log); + /* If the main log is piped, we need to make sure + * it is no longer used. The external log process + * (e.g. rotatelogs) will be gone now and the pipe will + * block, once the buffer gets full. Setting + * log_fd to -1 makes logging switch to error log. + */ + server_rec *s = (server_rec *) data; + jk_server_conf_t *conf = + (jk_server_conf_t *) ap_get_module_config(s->module_config, + &jk_module); + jk_logger_t *l = conf->log; + if (l && l->logger_private) { + jk_file_logger_t *p = l->logger_private; + if (p && p->is_piped == JK_TRUE) { + p->log_fd = -1; + p->is_piped = JK_FALSE; + } + } + jk_generic_cleanup(s); + jk_shm_close(l); } @@ -3589,17 +3621,6 @@ static void jk_server_cleanup(void *data static void jk_generic_cleanup(server_rec *s) { - /* If the main log is piped, we need to make sure - * it is no longer used. The external log process - * (e.g. rotatelogs) will be gone now and the pipe will - * block, once the buffer gets full - */ - if (main_log && main_log_is_piped && main_log->logger_private) { - jk_file_logger_t *p = main_log->logger_private; - if (p) { - p->log_fd = -1; - } - } if (jk_worker_properties) { jk_map_free(&jk_worker_properties); jk_worker_properties = NULL; Modified: tomcat/jk/trunk/native/apache-2.0/mod_jk.c URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/apache-2.0/mod_jk.c?rev=1649728&r1=1649727&r2=1649728&view=diff ============================================================================== --- tomcat/jk/trunk/native/apache-2.0/mod_jk.c (original) +++ tomcat/jk/trunk/native/apache-2.0/mod_jk.c Tue Jan 6 03:12:30 2015 @@ -169,7 +169,6 @@ typedef struct char *log_file; int log_level; jk_logger_t *log; - apr_file_t *jklogfp; /* * Mount stuff @@ -276,7 +275,6 @@ typedef struct apache_private_data apach static server_rec *main_server = NULL; static jk_logger_t *main_log = NULL; -static int main_log_is_piped = JK_FALSE; static apr_hash_t *jk_log_fps = NULL; static jk_worker_env_t worker_env; static apr_global_mutex_t *jk_log_lock = NULL; @@ -2645,16 +2643,19 @@ static apr_status_t jk_cleanup_proc(void { /* If the main log is piped, we need to make sure * it is no longer used. The external log process - * (e.g. rotatelogs) will be gone now and the pipe will - * block, once the buffer gets full + * (e.g. rotatelogs) will be gone now and the pipe will + * block, once the buffer gets full. NULLing + * jklogfp makes logging switch to error log. */ - if (main_log && main_log_is_piped && main_log->logger_private) { - jk_file_logger_t *p = main_log->logger_private; - if (p) { + jk_logger_t *l = (jk_logger_t *)data; + if (l && l->logger_private) { + jk_file_logger_t *p = l->logger_private; + if (p && p->is_piped == JK_TRUE) { p->jklogfp = NULL; + p->is_piped = JK_FALSE; } } - jk_shm_close(main_log); + jk_shm_close(l); return APR_SUCCESS; } @@ -2662,13 +2663,27 @@ static apr_status_t jk_cleanup_proc(void */ static apr_status_t jk_cleanup_child(void *data) { + /* If the main log is piped, we need to make sure + * it is no longer used. The external log process + * (e.g. rotatelogs) will be gone now and the pipe will + * block, once the buffer gets full. NULLing + * jklogfp makes logging switch to error log. + */ + jk_logger_t *l = (jk_logger_t *)data; + if (l && l->logger_private) { + jk_file_logger_t *p = l->logger_private; + if (p && p->is_piped == JK_TRUE) { + p->jklogfp = NULL; + p->is_piped = JK_FALSE; + } + } /* Force the watchdog thread exit */ if (jk_watchdog_interval > 0) { jk_watchdog_interval = 0; while (jk_watchdog_running) apr_sleep(apr_time_from_sec(1)); } - wc_shutdown(main_log); + wc_shutdown(l); return jk_cleanup_proc(data); } @@ -3272,7 +3287,6 @@ static int open_jklog(server_rec * s, ap apr_status_t rc; apr_file_t *jklogfp; piped_log *pl; - int is_piped = JK_FALSE; jk_logger_t *jkl; jk_file_logger_t *flp; int jklog_flags = (APR_WRITE | APR_APPEND | APR_CREATE); @@ -3305,7 +3319,6 @@ static int open_jklog(server_rec * s, ap return -1; } jklogfp = (void *)ap_piped_log_write_fd(pl); - is_piped = JK_TRUE; } else { fname = ap_server_root_relative(p, conf->log_file); @@ -3325,19 +3338,21 @@ static int open_jklog(server_rec * s, ap apr_file_inherit_set(jklogfp); apr_hash_set(jk_log_fps, conf->log_file, APR_HASH_KEY_STRING, jklogfp); } - conf->jklogfp = jklogfp; jkl = (jk_logger_t *)apr_palloc(p, sizeof(jk_logger_t)); flp = (jk_file_logger_t *) apr_palloc(p, sizeof(jk_file_logger_t)); if (jkl && flp) { jkl->log = jk_log_to_file; jkl->level = conf->log_level; jkl->logger_private = flp; - flp->jklogfp = conf->jklogfp; + flp->jklogfp = jklogfp; + if (*conf->log_file == '|') + flp->is_piped = JK_TRUE; + else + flp->is_piped = JK_FALSE; conf->log = jkl; jk_set_time_fmt(conf->log, conf->stamp_format_string); if (main_log == NULL) { main_log = conf->log; - main_log_is_piped = is_piped; /* hgomez@20070425 */ /* Shouldn't we clean both conf->log and main_log ? */ Modified: tomcat/jk/trunk/native/common/jk_logger.h URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_logger.h?rev=1649728&r1=1649727&r2=1649728&view=diff ============================================================================== --- tomcat/jk/trunk/native/common/jk_logger.h (original) +++ tomcat/jk/trunk/native/common/jk_logger.h Tue Jan 6 03:12:30 2015 @@ -57,6 +57,7 @@ struct jk_file_logger_t void *jklogfp; /* For Apache 1.3 piped logging */ int log_fd; + int is_piped; }; /* Level like Java tracing, but available only --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org