From 2b8fd9ceda9536ddd14eef6c02a41359480a108c Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 13 Jun 2005 00:35:19 +0000 Subject: [PATCH] Allow a few EINVALs from libevent before dying. Warn on kqueue with libevent before 1.1a svn:r4419 --- doc/TODO | 6 +++--- src/or/config.c | 3 ++- src/or/main.c | 22 ++++++++++++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/doc/TODO b/doc/TODO index 5a170af3c0..d7afebd0ff 100644 --- a/doc/TODO +++ b/doc/TODO @@ -46,9 +46,9 @@ For 0.1.0.x: - Is it the buf_shrink bug? (Quite possibly) - Instrument the 0.1.1 code to figure out where our memory is going; apply the results. (all platforms?) - - Why does kevent barf with EINVAL on some freebsd boxes? - - Submit libevent patch to Niels - - Warn on non-repeated EINVAL in Tor (don't die.) + . Why does kevent barf with EINVAL on some freebsd boxes? + o Submit libevent patch to Niels + o Warn on non-repeated EINVAL in Tor (don't die.) - Investigate why freebsd kernel actually does this: it doesn't seem simple to trigger. diff --git a/src/or/config.c b/src/or/config.c index dfb12ad09f..4784c412d6 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -2684,7 +2684,8 @@ check_libevent_version(const char *m, const char *v, int server) tor_assert(m && v); if (!strcmp(m, "kqueue")) { - if (!strcmp(v, "1.0c")) { + if (!strcmp(v, "1.0c") || !strcmp(v, "1.0d") || !strcmp(v, "1.0e") || + !strcmp(v, "1.1")) { buggy = 1; } } else if (!strcmp(m, "epoll")) { diff --git a/src/or/main.c b/src/or/main.c index 78d9047d62..e855c06ee1 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -810,6 +810,7 @@ run_scheduled_events(time_t now) } static struct event *timeout_event = NULL; +static int n_libevent_errors = 0; /** Libevent callback: invoked once every second. */ static void @@ -829,6 +830,8 @@ second_elapsed_callback(int fd, short event, void *args) one_second.tv_usec = 0; } + n_libevent_errors = 0; + /* log_fn(LOG_NOTICE, "Tick."); */ tor_gettimeofday(&now); @@ -885,6 +888,19 @@ second_elapsed_callback(int fd, short event, void *args) "Error from libevent when setting one-second timeout event"); } +/** Called when a possibly ignorable libevent error occurs; ensures that we + * don't get into an infinite loop by ignoring too many errors from + * libevent. */ +int +got_libevent_error(void) +{ + if (++n_libevent_errors > 8) { + log_fn(LOG_ERR, "Too many libevent errors in one second; dying"); + return -1; + } + return 0; +} + /** Called when we get a SIGHUP: reload configuration files and keys, * retry all connections, re-upload all descriptors, and so on. */ static int @@ -1001,6 +1017,12 @@ do_main_loop(void) tor_socket_strerror(e), e); #endif return -1; +#ifndef MS_WINDOWS + } else if (e == EINVAL) { + log_fn(LOG_WARN, "EINVAL from libevent: should you upgrade libevent?"); + if (got_libevent_error()) + return -1; +#endif } else { if (ERRNO_IS_EINPROGRESS(e)) log_fn(LOG_WARN,"libevent poll returned EINPROGRESS? Please report."); -- 2.11.4.GIT