diff options
author | Martin Schwenke <martin@meltin.net> | 2017-06-01 21:13:58 +1000 |
---|---|---|
committer | Martin Schwenke <martins@samba.org> | 2017-06-13 09:12:19 +0200 |
commit | d79c601fde6ec97e0463d42a133c5ec42193b025 (patch) | |
tree | 404db7e65ff00d5ea6008e5a715b25a47dce9407 /ctdb/common | |
parent | 323291a46e26e0493d43052550e57e2989b83b97 (diff) | |
download | samba-d79c601fde6ec97e0463d42a133c5ec42193b025.tar.gz |
ctdb-common: Log a count of dropped messages with non-blocking logging
The non-blocking logging variants can currently silently drop messages
when the socket queue fills.
In this case, count the number of dropped messages and attempt to log
a message about dropped log messages when the next message is logged.
Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Amitay Isaacs <amitay@gmail.com>
Diffstat (limited to 'ctdb/common')
-rw-r--r-- | ctdb/common/logging.c | 58 |
1 files changed, 53 insertions, 5 deletions
diff --git a/ctdb/common/logging.c b/ctdb/common/logging.c index 0e3efe0a728..f68c1b9d457 100644 --- a/ctdb/common/logging.c +++ b/ctdb/common/logging.c @@ -239,6 +239,7 @@ struct syslog_log_state { /* RFC3164 says: The total length of the packet MUST be 1024 bytes or less. */ char buffer[1024]; + unsigned int dropped_count; }; /* Format messages as per RFC3164 @@ -307,19 +308,66 @@ static void syslog_log(void *private_data, int level, const char *msg) syslog(debug_level_to_priority(level), "%s", msg); } -static void syslog_log_sock(void *private_data, int level, const char *msg) +static int syslog_log_sock_maybe(struct syslog_log_state *state, + int level, const char *msg) { - struct syslog_log_state *state = talloc_get_type_abort( - private_data, struct syslog_log_state); int n; + ssize_t ret; n = state->format(level, state, msg, state->buffer, sizeof(state->buffer)); if (n == -1) { - return; + return E2BIG; + } + + do { + ret = write(state->fd, state->buffer, n); + } while (ret == -1 && errno == EINTR); + + if (ret == -1) { + return errno; + } + + return 0; + +} +static void syslog_log_sock(void *private_data, int level, const char *msg) +{ + struct syslog_log_state *state = talloc_get_type_abort( + private_data, struct syslog_log_state); + int ret; + + if (state->dropped_count > 0) { + char t[64] = { 0 }; + snprintf(t, sizeof(t), + "[Dropped %u log messages]\n", + state->dropped_count); + t[sizeof(t)-1] = '\0'; + ret = syslog_log_sock_maybe(state, level, t); + if (ret == EAGAIN || ret == EWOULDBLOCK) { + state->dropped_count++; + /* + * If above failed then actually drop the + * message that would be logged below, since + * it would have been dropped anyway and it is + * also likely to fail. Falling through and + * attempting to log the message also means + * that the dropped message count will be + * logged out of order. + */ + return; + } + if (ret != 0) { + /* Silent failure on any other error */ + return; + } + state->dropped_count = 0; } - sys_write_v(state->fd, state->buffer, n); + ret = syslog_log_sock_maybe(state, level, msg); + if (ret == EAGAIN || ret == EWOULDBLOCK) { + state->dropped_count++; + } } static int syslog_log_setup_syslog(TALLOC_CTX *mem_ctx, const char *app_name) |