* 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;
}
}
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;
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, ...) {
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);
/* 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 */
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);
}