See initial patch attached. (30 seconds between reports is just to
make testing faster.)
Index: server/mpm/worker/worker.c
===================================================================
--- server/mpm/worker/worker.c (revision 906552)
+++ server/mpm/worker/worker.c (working copy)
@@ -1550,15 +1550,11 @@
/* no threads are "inactive" - starting, stopping, etc. */
/* have we reached MaxClients, or just getting close? */
if (0 == idle_thread_count) {
- static int reported = 0;
- if (!reported) {
- /* only report this condition once */
- ap_log_error(APLOG_MARK, APLOG_ERR, 0,
- ap_server_conf,
- "server reached MaxClients setting,
consider"
- " raising the MaxClients setting");
- reported = 1;
- }
+ static ap_log_interval_t interval = {0};
+ ap_log_error_interval(APLOG_MARK, APLOG_ERR,
apr_time_from_sec(30), 0,
+ &interval, 0, ap_server_conf,
+ "server reached MaxClients setting,
consider"
+ " raising the MaxClients setting");
} else {
static int reported = 0;
if (!reported) {
Index: include/http_log.h
===================================================================
--- include/http_log.h (revision 906552)
+++ include/http_log.h (working copy)
@@ -169,6 +169,17 @@
const char *fmt, ...)
__attribute__((format(printf,6,7)));
+typedef struct ap_log_interval_t {
+ apr_time_t last_report;
+ apr_int32_t count;
+} ap_log_interval_t;
+
+AP_DECLARE(void) ap_log_error_interval(const char *file, int line, int level,
+ apr_time_t max_interval, apr_int32_t
max_count,
+ ap_log_interval_t *state,
+ apr_status_t status, const server_rec
*s,
+ const char *fmt, ...);
+
/**
* ap_log_perror() - log messages which are not related to a particular
* request, connection, or virtual server. This uses a printf-like
Index: server/log.c
===================================================================
--- server/log.c (revision 906552)
+++ server/log.c (working copy)
@@ -732,6 +732,41 @@
va_end(args);
}
+AP_DECLARE(void) ap_log_error_interval(const char *file, int line, int level,
+ apr_time_t max_interval, apr_int32_t
max_count,
+ ap_log_interval_t *state,
+ apr_status_t status, const server_rec
*s,
+ const char *fmt, ...)
+{
+ va_list args;
+ char fmt_buf[512];
+ apr_time_t now;
+ int report = 0;
+
+ ++state->count;
+
+ if (max_interval != 0) {
+ now = apr_time_now();
+ if ((now - state->last_report) >= max_interval) {
+ report = 1;
+ }
+ }
+ else if (state->count >= max_count) {
+ report = 1;
+ }
+
+ if (report) {
+ apr_snprintf(fmt_buf, sizeof fmt_buf, "%s (occurred %u times)",
+ fmt, state->count);
+ va_start(args, fmt);
+ log_error_core(file, line, level, status, s, NULL, NULL, NULL,
fmt_buf, args);
+ va_end(args);
+
+ state->count = 0;
+ state->last_report = apr_time_now();
+ }
+}
+
AP_DECLARE(void) ap_log_perror(const char *file, int line, int level,
apr_status_t status, apr_pool_t *p,
const char *fmt, ...)