summaryrefslogtreecommitdiff
path: root/lib/zlog_targets.c
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@diac24.net>2021-04-10 21:02:06 +0200
committerDavid Lamparter <equinox@opensourcerouting.org>2021-04-21 16:25:33 +0200
commitdb2baed166581081db692fab0214752dbb121ed3 (patch)
tree67083421d6ac85080aa010ca9ef9ddf9cfc63be2 /lib/zlog_targets.c
parentbf6005d5f4f893817723e26b844831c22532f2f1 (diff)
lib: fix possible assert() fail in zlog_fd()
If the last message in a batched logging operation isn't printed due to priority, this skips the code that flushes prepared messages through writev() and can trigger the assert() at the end of zlog_fd(). Since any logmsg above info priority triggers a buffer flush, running into this situation requires a log file target configured for info priority, at least 1 message of info priority buffered, a debug message buffered after that, and then a buffer flush (explicit or due to buffer full). I haven't seen this chain of events happen in the wild, but it needs fixing anyway. Signed-off-by: David Lamparter <equinox@diac24.net>
Diffstat (limited to 'lib/zlog_targets.c')
-rw-r--r--lib/zlog_targets.c60
1 files changed, 34 insertions, 26 deletions
diff --git a/lib/zlog_targets.c b/lib/zlog_targets.c
index f258a8fbbd..7799fbfda7 100644
--- a/lib/zlog_targets.c
+++ b/lib/zlog_targets.c
@@ -78,40 +78,48 @@ void zlog_fd(struct zlog_target *zt, struct zlog_msg *msgs[], size_t nmsgs)
struct zlog_msg *msg = msgs[i];
int prio = zlog_msg_prio(msg);
- if (prio > zt->prio_min)
- continue;
-
- iov[iovpos].iov_base = ts_pos;
- if (iovpos > 0)
- *ts_pos++ = '\n';
- ts_pos += zlog_msg_ts(msg, ts_pos, sizeof(ts_buf) - 1
- - (ts_pos - ts_buf),
- ZLOG_TS_LEGACY | zte->ts_subsec);
- *ts_pos++ = ' ';
- iov[iovpos].iov_len = ts_pos - (char *)iov[iovpos].iov_base;
+ if (prio <= zt->prio_min) {
+ iov[iovpos].iov_base = ts_pos;
+ if (iovpos > 0)
+ *ts_pos++ = '\n';
+ ts_pos += zlog_msg_ts(msg, ts_pos,
+ sizeof(ts_buf) - 1
+ - (ts_pos - ts_buf),
+ ZLOG_TS_LEGACY | zte->ts_subsec);
+ *ts_pos++ = ' ';
+ iov[iovpos].iov_len =
+ ts_pos - (char *)iov[iovpos].iov_base;
- iovpos++;
+ iovpos++;
- if (zte->record_priority) {
- iov[iovpos].iov_base = (char *)prionames[prio];
- iov[iovpos].iov_len = strlen(iov[iovpos].iov_base);
+ if (zte->record_priority) {
+ iov[iovpos].iov_base = (char *)prionames[prio];
+ iov[iovpos].iov_len =
+ strlen(iov[iovpos].iov_base);
- iovpos++;
- }
+ iovpos++;
+ }
- iov[iovpos].iov_base = zlog_prefix;
- iov[iovpos].iov_len = zlog_prefixsz;
+ iov[iovpos].iov_base = zlog_prefix;
+ iov[iovpos].iov_len = zlog_prefixsz;
- iovpos++;
+ iovpos++;
- iov[iovpos].iov_base = (char *)zlog_msg_text(msg, &textlen);
- iov[iovpos].iov_len = textlen;
+ iov[iovpos].iov_base =
+ (char *)zlog_msg_text(msg, &textlen);
+ iov[iovpos].iov_len = textlen;
- iovpos++;
+ iovpos++;
+ }
- if (ts_buf + sizeof(ts_buf) - ts_pos < TS_LEN
- || i + 1 == nmsgs
- || array_size(iov) - iovpos < 5) {
+ /* conditions that trigger writing:
+ * - out of space for more timestamps/headers
+ * - this being the last message in the batch
+ * - not enough remaining iov entries
+ */
+ if (iovpos > 0 && (ts_buf + sizeof(ts_buf) - ts_pos < TS_LEN
+ || i + 1 == nmsgs
+ || array_size(iov) - iovpos < 5)) {
iov[iovpos].iov_base = (char *)"\n";
iov[iovpos].iov_len = 1;