s6

Mirror/fork of https://skarnet.org/software/s6/
git clone https://ccx.te2000.cz/git/s6
Log | Files | Refs | README | LICENSE

commit 7fba356b1378b0d470f746b45797c229e9d882cd
parent cedfe51030470abecc325b54656098376cc70305
Author: Laurent Bercot <ska-skaware@skarnet.org>
Date:   Fri, 22 Jan 2021 19:10:56 +0000

 bugfix: make s6-log -l actually split

Diffstat:
Mdoc/s6-log.html | 12+++++++-----
Msrc/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 @@ -68,11 +68,13 @@ Currently supported verbosity levels: <li> 1: write alerts, warnings and fatal errors </li> </ul> </li> <li> <tt>-l&nbsp;<em>linelimit</em></tt>&nbsp;: if a log line is longer than -<em>linelimit</em> bytes, cut it in two by inserting a newline. The newline -may appear anywhere after <em>linelimit</em> or more bytes. <em>linelimit</em> -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. </li> +<em>linelimit</em> bytes, split it by inserting a newline after the +<em>linelimit</em>th byte. After the split, the remainder of the line will +also be processed, so it will go through the selection process, timestamping, +etc. <em>linelimit</em> cannot be less than 48, unless it is 0 (which means +infinite). The default is 8192 bytes. Setting <em>linelimit</em> 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. </li> </ul> <h2> Logdirs </h2> diff --git a/src/daemontools-extras/s6-log.c b/src/daemontools-extras/s6-log.c @@ -31,7 +31,6 @@ #include <skalibs/sig.h> #include <skalibs/selfpipe.h> #include <skalibs/siovec.h> -#include <skalibs/skamisc.h> #include <skalibs/exec.h> #include <s6/config.h> @@ -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 ; } }