Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145619430
D41448.id125980.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D41448.id125980.diff
View Options
diff --git a//home/admin/stable.13/usr.sbin/syslogd/syslogd.c b//usr/src/usr.sbin/syslogd/syslogd.c
--- a//home/admin/stable.13/usr.sbin/syslogd/syslogd.c
+++ b//usr/src/usr.sbin/syslogd/syslogd.c
@@ -117,6 +117,7 @@
#include <sys/uio.h>
#include <sys/un.h>
#include <sys/wait.h>
+#include <sys/sysctl.h>
#if defined(INET) || defined(INET6)
#include <netinet/in.h>
@@ -256,6 +257,13 @@
* or if f_type is F_PIPE and f_pid > 0.
*/
+struct chunk_list {
+ STAILQ_ENTRY(chunk_list) next;
+ size_t size;
+ char *ptr;
+ char buf[];
+};
+
struct filed {
STAILQ_ENTRY(filed) next; /* next in linked list */
short f_type; /* entry type, see below */
@@ -280,6 +288,8 @@
struct {
char f_pname[MAXPATHLEN];
pid_t f_pid;
+ time_t queue_time;
+ STAILQ_HEAD(chunks_head, chunk_list) chunks;
} f_pipe;
} f_un;
#define fu_uname f_un.f_uname
@@ -368,6 +378,9 @@
"FORW", "USERS", "WALL", "PIPE"
};
+#define DEAD_QUEUE_TIME 10
+
+static uint64_t pipes_limit = 16*1024*1024, pipes_size;
static STAILQ_HEAD(, filed) fhead =
STAILQ_HEAD_INITIALIZER(fhead); /* Log files that we write to */
static struct filed consfile; /* Console */
@@ -413,7 +426,6 @@
struct iovlist;
static int allowaddr(char *);
-static int addfile(struct filed *);
static int addpeer(struct peer *);
static int addsock(struct addrinfo *, struct socklist *);
static struct filed *cfline(const char *, const char *, const char *,
@@ -459,10 +471,12 @@
static int waitdaemon(int);
static void timedout(int);
static void increase_rcvbuf(int);
+static void pipe_queue_write(struct filed *);
static void
close_filed(struct filed *f)
{
+ struct chunk_list *cl;
if (f == NULL || f->f_file == -1)
return;
@@ -482,6 +496,12 @@
break;
case F_PIPE:
f->fu_pipe_pid = 0;
+ struct chunk_list *tmp;
+ STAILQ_FOREACH_SAFE(cl, &f->f_un.f_pipe.chunks, next, tmp) {
+ STAILQ_REMOVE(&f->f_un.f_pipe.chunks, cl, chunk_list, next);
+ if(pipes_limit) pipes_size -= cl->size;
+ free(cl);
+ }
break;
}
(void)close(f->f_file);
@@ -489,20 +509,6 @@
}
static int
-addfile(struct filed *f0)
-{
- struct filed *f;
-
- f = calloc(1, sizeof(*f));
- if (f == NULL)
- err(1, "malloc failed");
- *f = *f0;
- STAILQ_INSERT_TAIL(&fhead, f, next);
-
- return (0);
-}
-
-static int
addpeer(struct peer *pe0)
{
struct peer *pe;
@@ -542,18 +548,26 @@
int
main(int argc, char *argv[])
{
- int ch, i, s, fdsrmax = 0, bflag = 0, pflag = 0, Sflag = 0;
+ int ch, i, s, fdsrmax = 0, fdswmax = 0, bflag = 0, pflag = 0, Sflag = 0;
fd_set *fdsr = NULL;
+ fd_set *fdsw = NULL;
struct timeval tv, *tvp;
struct peer *pe;
struct socklist *sl;
pid_t ppid = 1, spid;
char *p;
-
+ struct filed *f;
+ uint64_t usermem;
+ size_t usermem_len = sizeof(usermem);
+
if (madvise(NULL, 0, MADV_PROTECT) != 0)
dprintf("madvise() failed: %s\n", strerror(errno));
- while ((ch = getopt(argc, argv, "468Aa:b:cCdf:FHkl:M:m:nNoO:p:P:sS:Tuv"))
+ if (sysctlbyname("hw.usermem", &usermem, &usermem_len, NULL, 0) >= 0) {
+ pipes_limit = usermem / 128;
+ pipes_limit = MAX(pipes_limit, 128*1024);
+ }
+ while ((ch = getopt(argc, argv, "468Aa:b:cCdf:g:FHkl:M:m:nNoO:p:P:sS:Tuv"))
!= -1)
switch (ch) {
#ifdef INET
@@ -617,6 +631,10 @@
case 'F': /* run in foreground instead of daemon */
Foreground++;
break;
+ case 'g':
+ if (expand_number(optarg, &pipes_limit) == -1)
+ errx(EX_USAGE, "invalid global pipe limit: %s", optarg);
+ break;
case 'H':
RemoteHostname = 1;
break;
@@ -803,10 +821,18 @@
if (sl->sl_socket > fdsrmax)
fdsrmax = sl->sl_socket;
}
+ STAILQ_FOREACH(f, &fhead, next) {
+ if (f->f_type == F_PIPE && f->fu_pipe_pid && f->f_file > fdsrmax)
+ fdsrmax = f->f_file;
+ }
fdsr = (fd_set *)calloc(howmany(fdsrmax+1, NFDBITS),
sizeof(*fdsr));
if (fdsr == NULL)
errx(1, "calloc fd_set");
+ fdsw = (fd_set *)calloc(howmany(fdsrmax+1, NFDBITS),
+ sizeof(*fdsw));
+ if (fdsw == NULL)
+ errx(1, "calloc fd_set (write)");
for (;;) {
if (Initialized == 0)
@@ -819,17 +845,43 @@
markit();
if (WantDie) {
free(fdsr);
+ free(fdsw);
die(WantDie);
}
+ fdswmax = 0;
+ STAILQ_FOREACH(f, &fhead, next) {
+ if(f->f_type == F_PIPE && f->fu_pipe_pid && f->f_file > fdswmax)
+ fdswmax = f->f_file;
+ }
+ if(fdswmax > fdsrmax) {
+ fdsrmax = fdswmax;
+ free(fdsr);
+ fdsr = (fd_set *)calloc(howmany(fdsrmax+1, NFDBITS),
+ sizeof(*fdsr));
+ if (fdsr == NULL)
+ errx(1, "calloc fd_set");
+ free(fdsw);
+ fdsw = (fd_set *)calloc(howmany(fdsrmax+1, NFDBITS),
+ sizeof(*fdsw));
+ if (fdsw == NULL)
+ errx(1, "calloc fd_set (write)");
+ }
bzero(fdsr, howmany(fdsrmax+1, NFDBITS) *
sizeof(*fdsr));
+ bzero(fdsw, howmany(fdsrmax+1, NFDBITS) *
+ sizeof(*fdsw));
STAILQ_FOREACH(sl, &shead, next) {
if (sl->sl_socket != -1 && sl->sl_recv != NULL)
FD_SET(sl->sl_socket, fdsr);
}
- i = select(fdsrmax + 1, fdsr, NULL, NULL,
+
+ STAILQ_FOREACH(f, &fhead, next) {
+ if(f->f_type == F_PIPE && f->fu_pipe_pid && !STAILQ_EMPTY(&f->f_un.f_pipe.chunks))
+ FD_SET(f->f_file, fdsw);
+ }
+ i = select(fdsrmax + 1, fdsr, fdsw, NULL,
needdofsync ? &tv : tvp);
switch (i) {
case 0:
@@ -846,12 +898,31 @@
logerror("select");
continue;
}
+ STAILQ_FOREACH(f, &fhead, next) {
+ char buf[512];
+ if (f->f_type != F_PIPE)
+ continue;
+ if (f->fu_pipe_pid == 0 || STAILQ_EMPTY(&f->f_un.f_pipe.chunks))
+ continue;
+ if (FD_ISSET(f->f_file, fdsw)) {
+ pipe_queue_write(f);
+ continue;
+ }
+ if (time(NULL) - f->f_un.f_pipe.queue_time < DEAD_QUEUE_TIME)
+ continue;
+ deadq_enter(f->fu_pipe_pid, f->fu_pipe_pname);
+ close_filed(f);
+ errno = 0;
+ snprintf(buf, sizeof(buf), "pipe to %s stalled more then " __XSTRING(DEAD_QUEUE_TIME) " seconds, killed", f->fu_pipe_pname);
+ logerror(buf);
+ }
STAILQ_FOREACH(sl, &shead, next) {
if (FD_ISSET(sl->sl_socket, fdsr))
(*sl->sl_recv)(sl);
}
}
free(fdsr);
+ free(fdsw);
}
static int
@@ -1833,6 +1904,105 @@
#endif
static void
+pipe_failed(struct filed *f, int e)
+{
+ deadq_enter(f->fu_pipe_pid, f->fu_pipe_pname);
+ close_filed(f);
+ if (e == 0) {
+ char buf[512];
+
+ errno = 0;
+ snprintf(buf, sizeof(buf), "pipe to %s stalled more then " __XSTRING(DEAD_QUEUE_TIME) " seconds, killed", f->fu_pipe_pname);
+ logerror(buf);
+ } else if (e < 0) {
+ char buf[512];
+
+ errno = 0;
+ snprintf(buf, sizeof(buf), "pipes to %s try allocated more total limit bytes (%lu), killed", f->fu_pipe_pname, pipes_limit);
+ logerror(buf);
+ } else {
+ errno = e;
+ logerror(f->fu_pipe_pname);
+ }
+}
+
+static void
+pipe_queue_write(struct filed *f)
+{
+ struct chunk_list *cl, *tmp;
+ STAILQ_FOREACH_SAFE(cl, &f->f_un.f_pipe.chunks, next, tmp) {
+ size_t cnt = write(f->f_file, cl->ptr, cl->size);
+ if (cnt < 0) {
+ if (errno != EAGAIN)
+ pipe_failed(f, errno);
+ return;
+ }
+ f->f_un.f_pipe.queue_time = time(NULL);
+ if (pipes_limit) pipes_size -= cnt;
+ if (cnt != cl->size) {
+ cl->ptr += cnt;
+ cl->size -= cnt;
+ return;
+ }
+ STAILQ_REMOVE(&f->f_un.f_pipe.chunks, cl, chunk_list, next);
+ free(cl);
+ }
+}
+
+static void
+pipe_add_queue(struct filed *f, struct iovlist *il, size_t skip)
+{
+ char *p;
+ struct chunk_list *cl;
+
+ if (time(NULL) - f->f_un.f_pipe.queue_time >= DEAD_QUEUE_TIME) {
+ pipe_failed(f, 0);
+ return;
+ }
+ if (pipes_limit) {
+ if (pipes_size + il->totalsize - skip > pipes_limit) {
+ pipe_failed(f, -1);
+ return;
+ } else
+ pipes_size += il->totalsize - skip;
+ }
+ cl = malloc(sizeof(*cl) + il->totalsize - skip);
+ p = cl->ptr = cl->buf;
+ cl->size = il->totalsize - skip;
+ for(size_t i = 0; i < il->iovcnt; i++) {
+ if (skip < il->iov[i].iov_len) {
+ memcpy(p, skip + (char*)il->iov[i].iov_base, il->iov[i].iov_len - skip);
+ p += il->iov[i].iov_len - skip;
+ skip = 0;
+ } else
+ skip -= il->iov[i].iov_len;
+ }
+ struct chunks_head *ch = &f->f_un.f_pipe.chunks;
+ STAILQ_INSERT_TAIL(ch, cl, next);
+}
+
+static void
+pipe_write(struct filed *f, struct iovlist *il)
+{
+ if (!STAILQ_EMPTY(&f->f_un.f_pipe.chunks)) {
+ pipe_add_queue(f, il, 0);
+ return;
+ }
+ ssize_t cnt = writev(f->f_file, il->iov, il->iovcnt);
+ if (cnt == (ssize_t)il->totalsize)
+ return;
+ if (cnt < 0 && errno != EAGAIN) {
+ pipe_failed(f, errno);
+ return;
+ }
+ if (cnt < 0)
+ cnt = 0;
+ f->f_un.f_pipe.queue_time = time(NULL);
+ pipe_add_queue(f, il, cnt);
+ return;
+}
+
+static void
fprintlog_write(struct filed *f, struct iovlist *il, int flags)
{
struct msghdr msghdr;
@@ -1947,14 +2117,7 @@
break;
}
}
- if (writev(f->f_file, il->iov, il->iovcnt) < 0) {
- int e = errno;
-
- deadq_enter(f->fu_pipe_pid, f->fu_pipe_pname);
- close_filed(f);
- errno = e;
- logerror(f->fu_pipe_pname);
- }
+ pipe_write(f, il);
break;
case F_CONSOLE:
@@ -2533,8 +2696,7 @@
cline[i] = '\0';
f = cfline(cline, prog, host, pfilter);
if (f != NULL)
- addfile(f);
- free(f);
+ STAILQ_INSERT_TAIL(&fhead, f, next);
}
}
@@ -2647,12 +2809,10 @@
dprintf("cannot open %s\n", ConfFile);
f = cfline("*.ERR\t/dev/console", "*", "*", "*");
if (f != NULL)
- addfile(f);
- free(f);
+ STAILQ_INSERT_TAIL(&fhead, f, next);
f = cfline("*.PANIC\t*", "*", "*", "*");
if (f != NULL)
- addfile(f);
- free(f);
+ STAILQ_INSERT_TAIL(&fhead, f, next);
Initialized = 1;
return;
@@ -3161,6 +3321,8 @@
(void)strlcpy(f->fu_pipe_pname, p + 1,
sizeof(f->fu_pipe_pname));
f->f_type = F_PIPE;
+ f->f_un.f_pipe.queue_time = 0;
+ STAILQ_INIT(&f->f_un.f_pipe.chunks);
break;
case '*':
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 23, 6:37 AM (13 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28952307
Default Alt Text
D41448.id125980.diff (9 KB)
Attached To
Mode
D41448: Buffering syslogd output to pipe
Attached
Detach File
Event Timeline
Log In to Comment