Browse Source

Allow a few EINVALs from libevent before dying. Warn on kqueue with libevent before 1.1a

svn:r4419
Nick Mathewson 20 years ago
parent
commit
2b8fd9ceda
3 changed files with 27 additions and 4 deletions
  1. 3 3
      doc/TODO
  2. 2 1
      src/or/config.c
  3. 22 0
      src/or/main.c

+ 3 - 3
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.
 

+ 2 - 1
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")) {

+ 22 - 0
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.");