diff --git a/log.c b/log.c index a348cf6..1698651 100644 --- a/log.c +++ b/log.c @@ -51,6 +51,19 @@ */ +/* + * Common code for all logs. + */ +static proxy_ctx_t *proxy_ctx = NULL; + +static void +log_exceptcb(void) +{ + if (proxy_ctx) { + proxy_loopbreak(proxy_ctx); + } +} + /* * Error log. * Switchable between stderr and syslog. @@ -937,7 +950,8 @@ log_preinit(opts_t *opts) prepcb = log_content_file_prepcb; } if (!(content_log = logger_new(reopencb, opencb, closecb, - writecb, prepcb))) { + writecb, prepcb, + log_exceptcb))) { log_content_file_fini(); goto out; } @@ -945,18 +959,21 @@ log_preinit(opts_t *opts) if (opts->connectlog) { if (log_connect_preinit(opts->connectlog) == -1) goto out; - if (!(connect_log = logger_new(log_connect_reopencb, NULL, NULL, - log_connect_writecb, NULL))) { + if (!(connect_log = logger_new(log_connect_reopencb, + NULL, NULL, + log_connect_writecb, NULL, + log_exceptcb))) { log_connect_fini(); goto out; } } if (opts->certgendir) { if (!(cert_log = logger_new(NULL, NULL, NULL, log_cert_writecb, - NULL))) + NULL, log_exceptcb))) goto out; } - if (!(err_log = logger_new(NULL, NULL, NULL, log_err_writecb, NULL))) + if (!(err_log = logger_new(NULL, NULL, NULL, log_err_writecb, NULL, + log_exceptcb))) goto out; return 0; @@ -997,8 +1014,9 @@ log_preinit_undo(void) * Return -1 on errors, 0 otherwise. */ int -log_init(opts_t *opts, int clisock1, int clisock2) +log_init(opts_t *opts, proxy_ctx_t *ctx, int clisock1, int clisock2) { + proxy_ctx = ctx; if (err_log) if (logger_start(err_log) == -1) return -1; diff --git a/log.h b/log.h index 0cdfbd1..fe8c60c 100644 --- a/log.h +++ b/log.h @@ -29,6 +29,7 @@ #define LOG_H #include "opts.h" +#include "proxy.h" #include "logger.h" #include "attrib.h" @@ -69,7 +70,7 @@ int log_cert_submit(const char *, X509 *) NONNULL(1,2) WUNRES; int log_preinit(opts_t *) NONNULL(1) WUNRES; void log_preinit_undo(void); -int log_init(opts_t *, int, int) NONNULL(1) WUNRES; +int log_init(opts_t *, proxy_ctx_t *, int, int) NONNULL(1,2) WUNRES; void log_fini(void); int log_reopen(void) WUNRES; diff --git a/logger.c b/logger.c index 333fe03..c2d8ffa 100644 --- a/logger.c +++ b/logger.c @@ -49,6 +49,7 @@ struct logger { logger_close_func_t close; logger_prep_func_t prep; logger_write_func_t write; + logger_except_func_t except; thrqueue_t *queue; }; @@ -70,7 +71,7 @@ logger_clear(logger_t *logger) logger_t * logger_new(logger_reopen_func_t reopenfunc, logger_open_func_t openfunc, logger_close_func_t closefunc, logger_write_func_t writefunc, - logger_prep_func_t prepfunc) + logger_prep_func_t prepfunc, logger_except_func_t exceptfunc) { logger_t *logger; @@ -83,6 +84,7 @@ logger_new(logger_reopen_func_t reopenfunc, logger_open_func_t openfunc, logger->close = closefunc; logger->write = writefunc; logger->prep = prepfunc; + logger->except = exceptfunc; logger->queue = NULL; return logger; } @@ -186,16 +188,24 @@ logger_thread(void *arg) { logger_t *logger = arg; logbuf_t *lb; + int e = 0; while ((lb = thrqueue_dequeue(logger->queue))) { if (logbuf_ctl_isset(lb, LBFLAG_REOPEN)) { - logger->reopen(); + if (logger->reopen() != 0) + e = 1; } else if (logbuf_ctl_isset(lb, LBFLAG_OPEN)) { - logger->open(lb->fh); + if (logger->open(lb->fh) != 0) + e = 1; } else if (logbuf_ctl_isset(lb, LBFLAG_CLOSE)) { logger->close(lb->fh); } else { - logbuf_write_free(lb, logger->write); + if (logbuf_write_free(lb, logger->write) < 0) + e = 1; + } + + if (e && logger->except) { + logger->except(); } } diff --git a/logger.h b/logger.h index f0d1c52..c4c0a2a 100644 --- a/logger.h +++ b/logger.h @@ -39,11 +39,13 @@ typedef int (*logger_open_func_t)(void *); typedef void (*logger_close_func_t)(void *); typedef ssize_t (*logger_write_func_t)(void *, const void *, size_t); typedef logbuf_t * (*logger_prep_func_t)(void *, unsigned long, logbuf_t *); +typedef void (*logger_except_func_t)(void); typedef struct logger logger_t; logger_t * logger_new(logger_reopen_func_t, logger_open_func_t, logger_close_func_t, logger_write_func_t, - logger_prep_func_t) NONNULL(4) MALLOC; + logger_prep_func_t, logger_except_func_t) + NONNULL(4,6) MALLOC; void logger_free(logger_t *) NONNULL(1); int logger_start(logger_t *) NONNULL(1) WUNRES; void logger_leave(logger_t *) NONNULL(1); diff --git a/main.c b/main.c index 17ede1f..c5f34ff 100644 --- a/main.c +++ b/main.c @@ -950,7 +950,7 @@ main(int argc, char *argv[]) ssl_reinit(); /* Post-privdrop/chroot/detach initialization, thread spawning */ - if (log_init(opts, clisock[1], clisock[2]) == -1) { + if (log_init(opts, proxy, clisock[1], clisock[2]) == -1) { fprintf(stderr, "%s: failed to init log facility: %s\n", argv0, strerror(errno)); goto out_log_failed; diff --git a/proxy.c b/proxy.c index 14e6751..632f38c 100644 --- a/proxy.c +++ b/proxy.c @@ -208,7 +208,7 @@ proxy_signal_cb(evutil_socket_t fd, UNUSED short what, void *arg) case SIGQUIT: case SIGINT: case SIGHUP: - event_base_loopbreak(ctx->evbase); + proxy_loopbreak(ctx); break; case SIGUSR1: if (log_reopen() == -1) { @@ -393,6 +393,15 @@ proxy_run(proxy_ctx_t *ctx) } } +/* + * Break the loop of the proxy, causing the proxy_run to return. + */ +void +proxy_loopbreak(proxy_ctx_t *ctx) +{ + event_base_loopbreak(ctx->evbase); +} + /* * Free the proxy data structures. */ diff --git a/proxy.h b/proxy.h index 0ec82fa..349ce6a 100644 --- a/proxy.h +++ b/proxy.h @@ -35,6 +35,7 @@ typedef struct proxy_ctx proxy_ctx_t; proxy_ctx_t * proxy_new(opts_t *, int) NONNULL(1) MALLOC; void proxy_run(proxy_ctx_t *) NONNULL(1); +void proxy_loopbreak(proxy_ctx_t *) NONNULL(1); void proxy_free(proxy_ctx_t *) NONNULL(1); #endif /* !PROXY_H */