From owner-freebsd-bugs Tue Feb 13 12:10:14 2001 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id CAD2837B6A2 for ; Tue, 13 Feb 2001 12:10:05 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.1/8.11.1) id f1DKA5753831; Tue, 13 Feb 2001 12:10:05 -0800 (PST) (envelope-from gnats) Received: from sep.hamburg.com (sep.hamburg.com [194.64.112.14]) by hub.freebsd.org (Postfix) with ESMTP id DB70B37B491 for ; Tue, 13 Feb 2001 12:02:14 -0800 (PST) Received: (from hmo@localhost) by sep.hamburg.com (8.11.2/8.11.2/hmo03sep00) id f1DK26e84391; Tue, 13 Feb 2001 21:02:07 +0100 (CET) (envelope-from hmo) Message-Id: <200102132002.f1DK26e84391@sep.hamburg.com> Date: Tue, 13 Feb 2001 21:02:07 +0100 (CET) From: newsyslog@oldach.net Reply-To: newsyslog@oldach.net To: FreeBSD-gnats-submit@freebsd.org Cc: hmo@sep.hamburg.com X-Send-Pr-Version: 3.2 Subject: bin/25070: newsyslog enhancement Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >Number: 25070 >Category: bin >Synopsis: newsyslog(8) should send signals only once per run >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Tue Feb 13 12:10:02 PST 2001 >Closed-Date: >Last-Modified: >Originator: Helge Oldach >Release: FreeBSD 4.2-STABLE i386 >Organization: >Environment: src/usr.sbin/newsyslog/newsyslog.c $FreeBSD: /ctm/FreeBSD/anoncvs/cvs/src/usr.sbin/newsyslog/newsyslog.c,v 1.25.2.2 2000/10/20 00:44:27 joe Exp $ FreeBSD sep 4.2-STABLE FreeBSD 4.2-STABLE #0: Mon Feb 5 14:13:12 CET 2001 toor@sep:/usr/obj/usr/src/sys/HMO i386 as of 12th February 2001 >Description: newsyslog(8) can send signals to the process ids contained in the PID files, per newsyslog.conf configuration files. Unfortunately a separate signal is sent for every configuration line. IMHO it would be better to send a signal for every process, covering the situation that a process may have multiple log files open that will all be closed when the signal is received. One example might be an Apache server with many virtual hosts, each of which writes into two separate logfiles (access.log and error.log), viz: /var/log/virt1-httpd-access.log 644 7 * @T00 ZB /var/run/httpd.pid 30 /var/log/virt1-httpd-error.log 644 7 * @T00 ZB /var/run/httpd.pid 30 /var/log/virt2-httpd-access.log 644 7 * @T00 ZB /var/run/httpd.pid 30 /var/log/virt2-httpd-error.log 644 7 * @T00 ZB /var/run/httpd.pid 30 /var/log/virt3-httpd-access.log 644 7 * @T00 ZB /var/run/httpd.pid 30 /var/log/virt3-httpd-error.log 644 7 * @T00 ZB /var/run/httpd.pid 30 This will currently restart Apache six (!) times when logfiles are due for rotation. As there is a delay of 10 seconds after each signal to allow the daemon to idle down, a longer newslog.conf file may easily take many minutes to complete. >How-To-Repeat: >Fix: This patch will delay sending signals and logfile compression until the entire newslog.conf file has been processed. All lines not involving signals are precessed immediately. Then, we send one signal (unique per PID and per signal number, hence it is possible to send different signals to one PID), we wait 10 seconds and finally we compress the old logs. This patch was meant to minimize changes to newsyslog.c. Of course the structure and logic should be reorganized to include this in the source in a more orthogonal fashion. --- newsyslog.c.ORIG Fri Oct 20 13:27:03 2000 +++ newsyslog.c Mon Feb 12 06:51:39 2001 @@ -81,6 +81,22 @@ struct conf_entry *next;/* Linked list pointer */ }; +struct log_entry { + char *log; /* name of the log to be compressed */ + struct log_entry* next; /* Linked list pointer */ +}; + +struct kill_entry { + pid_t pid; /* PID to kill */ + int sig; /* Signal to send */ + struct kill_entry* next;/* Linked list pointer */ +}; + +struct kill_entry* kill_pending = NULL; + /* List of PIDs to be killed */ +struct log_entry* log_pending = NULL; + /* List of logs to be compressed */ + int archtodir = 0; /* Archive old logfiles to other directory */ int verbose = 0; /* Print out what's going on */ int needroot = 1; /* Root privs are necessary */ @@ -99,6 +115,8 @@ static char *sob(char *p); static char *son(char *p); static char *missing_field(char *p, char *errline); +static int save_kill(pid_t pid, int sig); +static void save_compress_log(char* file); static void do_entry(struct conf_entry * ent); static void PRS(int argc, char **argv); static void usage(); @@ -117,6 +135,9 @@ main(int argc, char **argv) { struct conf_entry *p, *q; + struct kill_entry* k; + struct log_entry* l; + int notified; PRS(argc, argv); if (needroot && getuid() && geteuid()) @@ -129,6 +150,34 @@ free((char *) q); q = p; } + + notified = 0; + while (kill_pending) { + if (kill(kill_pending->pid, kill_pending->sig)) + warn("can't notify daemon, pid %d", (int) kill_pending->pid); + else { + notified = 1; + if (verbose) + printf("daemon pid %d notified\n", (int) kill_pending->pid); + } + k = kill_pending; + kill_pending = kill_pending->next; + free((char *) k); + } + if (notified) { + if (verbose) + printf("small pause to allow daemons to close logs\n"); + sleep(10); + } + + while (log_pending) { + compress_log(log_pending->log); + free(log_pending->log); + l = log_pending; + log_pending = log_pending->next; + free((char *) l); + } + return (0); } @@ -470,6 +519,38 @@ return (p); } +static int +save_kill(pid_t pid, int sig) +{ + struct kill_entry* p; + + for (p = kill_pending; p != NULL; p = p->next) + if (p->pid == pid && p->sig == sig) + return (0); + + p = (struct kill_entry *) malloc(sizeof(struct kill_entry)); + p->pid = pid; + p->sig = sig; + p->next = kill_pending; + kill_pending = p; + return (0); +} + +static void +save_compress_log(char *file) +{ + struct log_entry* p; + + for (p = log_pending; p != NULL; p = p->next) + if (!strcmp(p->log, file)) + return; + + p = (struct log_entry *) malloc(sizeof(struct log_entry)); + p->log = strdup(file); + p->next = log_pending; + log_pending = p; +} + static void dotrim(char *log, char *pid_file, int numdays, int flags, int perm, int owner_uid, int group_gid, int sig) @@ -613,12 +694,12 @@ if (noaction) { notified = 1; printf("kill -%d %d\n", sig, (int) pid); - } else if (kill(pid, sig)) + } else if (save_kill(pid, sig)) warn("can't notify daemon, pid %d", (int) pid); else { notified = 1; if (verbose) - printf("daemon pid %d notified\n", (int) pid); + printf("will notify daemon pid %d\n", (int) pid); } } if ((flags & CE_COMPACT)) { @@ -627,16 +708,11 @@ else if (noaction) printf("Compress %s.0\n", log); else { - if (notified) { - if (verbose) - printf("small pause to allow daemon to close log\n"); - sleep(10); - } if (archtodir) { (void) sprintf(file1, "%s/%s", dirpart, namepart); - compress_log(file1); + (pid == 0 ? compress_log : save_compress_log)(file1); } else { - compress_log(log); + (pid == 0 ? compress_log : save_compress_log)(log); } } } >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message