From 4f8d27f29a29db6afd0fbb941c00d4eaee860e90 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Sat, 3 Feb 2007 00:52:17 +0000 Subject: [PATCH] svlogd: do not set O_NONBLOCK on stdin permanently - that can affect other processes! --- runit/svlogd.c | 72 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/runit/svlogd.c b/runit/svlogd.c index 59b1e5721..a0e562b21 100644 --- a/runit/svlogd.c +++ b/runit/svlogd.c @@ -44,15 +44,19 @@ static int wstat; static struct taia trotate; static char *line; -static unsigned exitasap; -static unsigned rotateasap; -static unsigned reopenasap; -static unsigned linecomplete = 1; -static unsigned tmaxflag; -static iopause_fd input; +static smallint exitasap; +static smallint rotateasap; +static smallint reopenasap; +static smallint linecomplete = 1; + +static smallint tmaxflag; -static const char *replace = ""; static char repl; +static const char *replace = ""; + +sigset_t blocked_sigset; +static iopause_fd input; +static int fl_flag_0; static struct logdir { //// char *btmp; @@ -333,7 +337,7 @@ static int buffer_pwrite(int n, char *s, unsigned len) if (len > (ld->sizemax - ld->size)) len = ld->sizemax - ld->size; } - while ((i = write(ld->fdcur, s, len)) == -1) { + while ((i = full_write(ld->fdcur, s, len)) == -1) { if ((errno == ENOSPC) && (ld->nmin < ld->nmax)) { DIR *d; struct dirent *f; @@ -585,6 +589,17 @@ static void logdirs_reopen(void) if (!ok) fatalx("no functional log directories"); } +/* Will look good in libbb one day */ +static ssize_t ndelay_read(int fd, void *buf, size_t count) +{ + if (!(fl_flag_0 & O_NONBLOCK)) + fcntl(fd, F_SETFL, fl_flag_0 | O_NONBLOCK); + count = safe_read(fd, buf, count); + if (!(fl_flag_0 & O_NONBLOCK)) + fcntl(fd, F_SETFL, fl_flag_0); + return count; +} + /* Used for reading stdin */ static int buffer_pread(int fd, char *s, unsigned len) { @@ -617,17 +632,10 @@ static int buffer_pread(int fd, char *s, unsigned len) } while (1) { - /* Comment? */ - sig_unblock(SIGTERM); - sig_unblock(SIGCHLD); - sig_unblock(SIGALRM); - sig_unblock(SIGHUP); + sigprocmask(SIG_UNBLOCK, &blocked_sigset, NULL); iopause(&input, 1, &trotate, &now); - sig_block(SIGTERM); - sig_block(SIGCHLD); - sig_block(SIGALRM); - sig_block(SIGHUP); - i = safe_read(fd, s, len); + sigprocmask(SIG_BLOCK, &blocked_sigset, NULL); + i = ndelay_read(fd, s, len); if (i >= 0) break; if (errno != EAGAIN) { warn("cannot read standard input"); @@ -775,14 +783,17 @@ int svlogd_main(int argc, char **argv) fndir = argv; input.fd = 0; input.events = IOPAUSE_READ; - /* I be damned. Linux 2.6.18: this somehow affects - * OTHER processes! Konsole starts to redraw itself much slower! - * This persists even after svlogd exits */ - ndelay_on(input.fd); - sig_block(SIGTERM); - sig_block(SIGCHLD); - sig_block(SIGALRM); - sig_block(SIGHUP); + /* We cannot set NONBLOCK on fd #0 permanently - this setting + * _isn't_ per-process! It is shared among all other processes + * with the same stdin */ + fl_flag_0 = fcntl(0, F_GETFL, 0); + + sigemptyset(&blocked_sigset); + sigaddset(&blocked_sigset, SIGTERM); + sigaddset(&blocked_sigset, SIGCHLD); + sigaddset(&blocked_sigset, SIGALRM); + sigaddset(&blocked_sigset, SIGHUP); + sigprocmask(SIG_BLOCK, &blocked_sigset, NULL); sig_catch(SIGTERM, sig_term_handler); sig_catch(SIGCHLD, sig_child_handler); sig_catch(SIGALRM, sig_alarm_handler); @@ -850,8 +861,13 @@ int svlogd_main(int argc, char **argv) /* linelen == no of chars incl. '\n' (or == stdin_cnt) */ ch = lineptr[linelen-1]; - /* write out lineptr[0..linelen-1] to each log destination */ - /* (or lineptr[-26..linelen-1] if timestamping) */ + /* TODO: biggest performance hit is coming from the fact + * that we do not buffer writes. We may read many lines + * in one read() above, but will do one write() + * per line below. Should we use stdio? */ + + /* write out lineptr[0..linelen-1] to each log destination + * (or lineptr[-26..linelen-1] if timestamping) */ printlen = linelen; printptr = lineptr; if (timestamp) {