From 7fba356b1378b0d470f746b45797c229e9d882cd Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Fri, 22 Jan 2021 19:10:56 +0000 Subject: bugfix: make s6-log -l actually split --- doc/s6-log.html | 12 ++++++----- src/daemontools-extras/s6-log.c | 45 +++++++++++++++++++++++++++-------------- 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/doc/s6-log.html b/doc/s6-log.html index 7f461bc..158dd57 100644 --- a/doc/s6-log.html +++ b/doc/s6-log.html @@ -68,11 +68,13 @@ Currently supported verbosity levels:
  • 1: write alerts, warnings and fatal errors
  • -l linelimit : if a log line is longer than -linelimit bytes, cut it in two by inserting a newline. The newline -may appear anywhere after linelimit or more bytes. linelimit -cannot be less than 48. Using this option ensures that an ill-formatted log -stream will not make s6-log uncontrollably eat memory by trying to read and -process an extremely long line in one go. The default is 8192 bytes.
  • +linelimit bytes, split it by inserting a newline after the +linelimitth byte. After the split, the remainder of the line will +also be processed, so it will go through the selection process, timestamping, +etc. linelimit cannot be less than 48, unless it is 0 (which means +infinite). The default is 8192 bytes. Setting linelimit to 0 ensures +that lines will never be split; this may cause important memory consumption +by s6-log if it is fed extremely long lines, so use with caution.

    Logdirs

    diff --git a/src/daemontools-extras/s6-log.c b/src/daemontools-extras/s6-log.c index f3355f0..7959222 100644 --- a/src/daemontools-extras/s6-log.c +++ b/src/daemontools-extras/s6-log.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -1010,6 +1009,29 @@ static void prepare_to_exit (void) flagexiting = 1 ; } +static inline int getchunk (buffer *b, stralloc *sa, size_t linelimit) +{ + struct iovec v[2] ; + size_t pos ; + int r ; + buffer_rpeek(b, v) ; + pos = siovec_bytein(v, 2, "\n", 2) ; + if (linelimit && sa->len + pos > linelimit) + { + r = 2 ; + pos = linelimit - sa->len ; + } + else + { + r = pos < buffer_len(b) ; + pos += r ; + } + if (!stralloc_readyplus(sa, pos + (r == 2))) return -1 ; + buffer_getnofill(b, sa->s + sa->len, pos) ; sa->len += pos ; + if (r == 2) sa->s[sa->len++] = 0 ; + return r ; +} + static void normal_stdin (scriptelem_t const *script, unsigned int scriptlen, size_t linelimit, unsigned int gflags) { ssize_t r = sanitize_read(buffer_fill(buffer_0)) ; @@ -1018,21 +1040,14 @@ static void normal_stdin (scriptelem_t const *script, unsigned int scriptlen, si if ((errno != EPIPE) && verbosity) strerr_warnwu1sys("read from stdin") ; prepare_to_exit() ; } - else if (r) + else if (r) for (;;) { - while (skagetln_nofill(buffer_0, &indata, '\n') > 0) - { - indata.s[indata.len - 1] = 0 ; - script_run(script, scriptlen, indata.s, indata.len - 1, gflags) ; - indata.len = 0 ; - } - if (linelimit && indata.len > linelimit) - { - if (!stralloc_0(&indata)) dienomem() ; - if (verbosity) strerr_warnw2x("input line too long, ", "inserting a newline") ; - script_run(script, scriptlen, indata.s, indata.len - 1, gflags) ; - indata.len = 0 ; - } + r = getchunk(buffer_0, &indata, linelimit) ; + if (r < 0) dienomem() ; + else if (!r) break ; + indata.s[indata.len - 1] = 0 ; + script_run(script, scriptlen, indata.s, indata.len - 1, gflags) ; + indata.len = 0 ; } } -- cgit v1.2.3