svlogd: do not set O_NONBLOCK on stdin permanently - that can

affect other processes!
This commit is contained in:
Denis Vlasenko 2007-02-03 00:52:17 +00:00
parent 493691a4f5
commit 4f8d27f29a

View File

@ -44,15 +44,19 @@ static int wstat;
static struct taia trotate; static struct taia trotate;
static char *line; static char *line;
static unsigned exitasap; static smallint exitasap;
static unsigned rotateasap; static smallint rotateasap;
static unsigned reopenasap; static smallint reopenasap;
static unsigned linecomplete = 1; static smallint linecomplete = 1;
static unsigned tmaxflag;
static iopause_fd input; static smallint tmaxflag;
static const char *replace = "";
static char repl; static char repl;
static const char *replace = "";
sigset_t blocked_sigset;
static iopause_fd input;
static int fl_flag_0;
static struct logdir { static struct logdir {
//// char *btmp; //// char *btmp;
@ -333,7 +337,7 @@ static int buffer_pwrite(int n, char *s, unsigned len)
if (len > (ld->sizemax - ld->size)) if (len > (ld->sizemax - ld->size))
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)) { if ((errno == ENOSPC) && (ld->nmin < ld->nmax)) {
DIR *d; DIR *d;
struct dirent *f; struct dirent *f;
@ -585,6 +589,17 @@ static void logdirs_reopen(void)
if (!ok) fatalx("no functional log directories"); 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 */ /* Used for reading stdin */
static int buffer_pread(int fd, char *s, unsigned len) 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) { while (1) {
/* Comment? */ sigprocmask(SIG_UNBLOCK, &blocked_sigset, NULL);
sig_unblock(SIGTERM);
sig_unblock(SIGCHLD);
sig_unblock(SIGALRM);
sig_unblock(SIGHUP);
iopause(&input, 1, &trotate, &now); iopause(&input, 1, &trotate, &now);
sig_block(SIGTERM); sigprocmask(SIG_BLOCK, &blocked_sigset, NULL);
sig_block(SIGCHLD); i = ndelay_read(fd, s, len);
sig_block(SIGALRM);
sig_block(SIGHUP);
i = safe_read(fd, s, len);
if (i >= 0) break; if (i >= 0) break;
if (errno != EAGAIN) { if (errno != EAGAIN) {
warn("cannot read standard input"); warn("cannot read standard input");
@ -775,14 +783,17 @@ int svlogd_main(int argc, char **argv)
fndir = argv; fndir = argv;
input.fd = 0; input.fd = 0;
input.events = IOPAUSE_READ; input.events = IOPAUSE_READ;
/* I be damned. Linux 2.6.18: this somehow affects /* We cannot set NONBLOCK on fd #0 permanently - this setting
* OTHER processes! Konsole starts to redraw itself much slower! * _isn't_ per-process! It is shared among all other processes
* This persists even after svlogd exits */ * with the same stdin */
ndelay_on(input.fd); fl_flag_0 = fcntl(0, F_GETFL, 0);
sig_block(SIGTERM);
sig_block(SIGCHLD); sigemptyset(&blocked_sigset);
sig_block(SIGALRM); sigaddset(&blocked_sigset, SIGTERM);
sig_block(SIGHUP); 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(SIGTERM, sig_term_handler);
sig_catch(SIGCHLD, sig_child_handler); sig_catch(SIGCHLD, sig_child_handler);
sig_catch(SIGALRM, sig_alarm_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) */ /* linelen == no of chars incl. '\n' (or == stdin_cnt) */
ch = lineptr[linelen-1]; ch = lineptr[linelen-1];
/* write out lineptr[0..linelen-1] to each log destination */ /* TODO: biggest performance hit is coming from the fact
/* (or lineptr[-26..linelen-1] if timestamping) */ * 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; printlen = linelen;
printptr = lineptr; printptr = lineptr;
if (timestamp) { if (timestamp) {