From f6033c46c877646b95bc2e99ce69097203bc5c77 Mon Sep 17 00:00:00 2001 From: Richard Kettlewell Date: Sun, 4 Nov 2007 11:16:14 +0000 Subject: [PATCH 1/1] avoid crashes on log client teardown --- lib/event.c | 2 ++ lib/eventlog.c | 8 ++++++-- server/server.c | 17 ++++++++++++++--- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/lib/event.c b/lib/event.c index bb9d4ea..9c48ed1 100644 --- a/lib/event.c +++ b/lib/event.c @@ -978,6 +978,8 @@ ev_writer *ev_writer_new(ev_source *ev, * descriptor as and when it is writable. */ struct sink *ev_writer_sink(ev_writer *w) { + if(!w) + fatal(0, "ev_write_sink called with null writer"); return &w->s; } diff --git a/lib/eventlog.c b/lib/eventlog.c index e652e22..b9ae495 100644 --- a/lib/eventlog.c +++ b/lib/eventlog.c @@ -48,7 +48,7 @@ void eventlog_remove(struct eventlog_output *lo) { } static void veventlog(const char *keyword, const char *raw, va_list ap) { - struct eventlog_output *p; + struct eventlog_output *p, *pnext; struct dynstr d; const char *param; @@ -63,8 +63,12 @@ static void veventlog(const char *keyword, const char *raw, va_list ap) { dynstr_append_string(&d, raw); } dynstr_terminate(&d); - for(p = outputs; p; p = p->next) + for(p = outputs; p; p = pnext) { + /* We must be able to cope with eventlog_remove() being called from inside + * the callback */ + pnext = p; p->fn(d.vec, p->user); + } } void eventlog_raw(const char *keyword, const char *raw, ...) { diff --git a/server/server.c b/server/server.c index 35f352d..1e4c6ca 100644 --- a/server/server.c +++ b/server/server.c @@ -142,7 +142,10 @@ static int reader_error(ev_source attribute((unused)) *ev, D(("server reader_error %d %d", fd, errno_value)); error(errno, "S%x read error on socket", c->tag); - ev_writer_cancel(c->w); + if(c->w) { + ev_writer_cancel(c->w); + c->w = 0; + } ev_report(ev); info("reader_error closing fd %d", fd); /* TODO */ xclose(fd); @@ -732,8 +735,11 @@ static int logging_reader_callback(ev_source *ev, /* don't log to this conn any more */ eventlog_remove(c->lo); - /* terminate the log output */ - sink_writes(ev_writer_sink(c->w), ".\n"); + if(c->w) { + /* Terminate the log output, but only if the writer hasn't been killed off + * from a failure on some earlier write */ + sink_writes(ev_writer_sink(c->w), ".\n"); + } /* restore the reader callback */ c->reader = reader_callback; /* ...and exit via it */ @@ -743,6 +749,11 @@ static int logging_reader_callback(ev_source *ev, static void logclient(const char *msg, void *user) { struct conn *c = user; + if(!c->w || !c->r) { + /* This connection has gone up in smoke for some reason */ + eventlog_remove(c->lo); + return; + } sink_printf(ev_writer_sink(c->w), "%"PRIxMAX" %s\n", (uintmax_t)time(0), msg); } -- 2.11.0