[or-cvs] [tor/master] Move the Libvent setup logic into compat_libevent from config.

Nick Mathewson nickm at seul.org
Fri Jun 12 18:28:06 UTC 2009


Author: Nick Mathewson <nickm at torproject.org>
Date: Thu, 4 Jun 2009 03:16:26 -0400
Subject: Move the Libvent setup logic into compat_libevent from config.
Commit: c0af3cdfb6816659031fed5a1b8feec5d457b608

This has been some pretty ugly and voodoo-laden code.  I've tried to
clean it up a bit, but more work probably remains.
---
 configure.in                 |    2 +-
 src/common/compat_libevent.c |  305 ++++++++++++++++++++++++++++++++++++++++++
 src/common/compat_libevent.h |   11 +-
 src/or/config.c              |  251 +---------------------------------
 src/or/or.h                  |    6 +
 5 files changed, 328 insertions(+), 247 deletions(-)

diff --git a/configure.in b/configure.in
index 5720244..f9a7b03 100644
--- a/configure.in
+++ b/configure.in
@@ -273,7 +273,7 @@ save_CPPFLAGS="$CPPFLAGS"
 LIBS="-levent $TOR_LIB_WS32 $LIBS"
 LDFLAGS="$TOR_LDFLAGS_libevent $LDFLAGS"
 CPPFLAGS="$TOR_CPPFLAGS_libevent $CPPFLAGS"
-AC_CHECK_FUNCS(event_get_version event_get_method event_set_log_callback evdns_set_outgoing_bind_address)
+AC_CHECK_FUNCS(event_get_version event_get_version_number event_get_method event_set_log_callback evdns_set_outgoing_bind_address)
 AC_CHECK_MEMBERS([struct event.min_heap_idx], , ,
 [#include <event.h>
 ])
diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c
index d2ef112..ce9f6a0 100644
--- a/src/common/compat_libevent.c
+++ b/src/common/compat_libevent.c
@@ -23,6 +23,21 @@
 #include <event.h>
 #endif
 
+/** A number representing a version of Libevent.
+
+    This is a 4-byte number, with the first three bytes representing the
+    major, minor, and patchlevel respectively of the the library.  The fourth
+    byte is unused.
+
+    This is equivalent to the format of LIBEVENT_VERSION_NUMBER on Libevent
+    2.0.1 or later.  For versions of Libevent before 1.4.0, which followed the
+    format of "1.0, 1.0a, 1.0b", we define 1.0 to be equivalent to 1.0.0, 1.0a
+    to be equivalent to 1.0.1, and so on.
+*/
+typedef uint32_t le_version_t;
+
+static le_version_t tor_get_libevent_version(const char **v_out);
+
 #ifdef HAVE_EVENT_SET_LOG_CALLBACK
 /** A string which, if it appears in a libevent log, should be ignored. */
 static const char *suppress_msg = NULL;
@@ -119,16 +134,51 @@ tor_event_free(struct event *ev)
 /** Global event base for use by the main thread. */
 struct event_base *the_event_base = NULL;
 
+
+/* This is what passes for version detection on OSX.  We set
+ * MACOSX_KQUEUE_IS_BROKEN to true iff we're on a version of OSX before
+ * 10.4.0 (aka 1040). */
+#ifdef __APPLE__
+#ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
+#define MACOSX_KQUEUE_IS_BROKEN \
+  (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1040)
+#else
+#define MACOSX_KQUEUE_IS_BROKEN 0
+#endif
+#endif
+
 /** Initialize the Libevent library and set up the event base. */
 void
 tor_libevent_initialize(void)
 {
   tor_assert(the_event_base == NULL);
+
+#ifdef __APPLE__
+  if (MACOSX_KQUEUE_IS_BROKEN ||
+      tor_get_libevent_version(NULL) < V_OLD(1,1,'b')) {
+    setenv("EVENT_NOKQUEUE","1",1);
+  }
+#endif
+
 #ifdef HAVE_EVENT2_EVENT_H
   the_event_base = event_base_new();
 #else
   the_event_base = event_init();
 #endif
+
+#if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
+  /* Making this a NOTICE for now so we can link bugs to a libevent versions
+   * or methods better. */
+  log(LOG_NOTICE, LD_GENERAL,
+      "Initialized libevent version %s using method %s. Good.",
+      event_get_version(), tor_libevent_get_method());
+#else
+  log(LOG_NOTICE, LD_GENERAL,
+      "Initialized old libevent (version 1.0b or earlier).");
+  log(LOG_WARN, LD_GENERAL,
+      "You have a *VERY* old version of libevent.  It is likely to be buggy; "
+      "please build Tor with a more recent version.");
+#endif
 }
 
 /** Return the current Libevent event base that we're set up to use. */
@@ -151,3 +201,258 @@ tor_libevent_get_method(void)
 #endif
 }
 
+/* Macros: returns the number of a libevent version. */
+#define V(major, minor, patch) \
+  (((major) << 24) | ((minor) << 16) | ((patch) << 8))
+#define V_OLD(major, minor, patch) \
+  V((major), (minor), (patch)-'a'+1)
+
+#define LE_OLD V(0,0,0)
+#define LE_OTHER V(0,0,99)
+
+/** Return the le_version_t for the current version of libevent.  If the
+ * version is very new, return LE_OTHER.  If the version is so old that it
+ * doesn't support event_get_version(), return LE_OLD. DOCDOC */
+static le_version_t
+tor_decode_libevent_version(const char *v)
+{
+  unsigned major, minor, patchlevel;
+  char c, extra;
+  int fields;
+
+  /* Try the new preferred "1.4.11-stable" format. */
+  fields = sscanf(v, "%u.%u.%u%c", &major, &minor, &patchlevel, &c);
+  if (fields == 3 ||
+      (fields == 4 && (c == '-' || c == '_'))) {
+    return V(major,minor,patchlevel);
+  }
+
+  /* Try the old "1.3e" format. */
+  fields = sscanf(v, "%u.%u%c%c", &major, &minor, &c, &extra);
+  if (fields == 3 && TOR_ISALPHA(c)) {
+    return V_OLD(major, minor, c);
+  } else if (fields == 2) {
+    return V(major, minor, 0);
+  }
+
+  return LE_OTHER;
+}
+
+/** Return an integer representing the binary interface of a Libevent library.
+ * Two different versions with different numbers are sure not to be binary
+ * compatible.  Two different versions with the same numbers have a decent
+ * chance of binary compatibility.*/
+static int
+le_versions_compatibility(le_version_t v)
+{
+  if (v == LE_OTHER)
+    return 0;
+  if (v < V_OLD(1,0,'c'))
+    return 1;
+  else if (v < V(1,4,0))
+    return 2;
+  else if (v < V(1,4,99))
+    return 3;
+  else if (v < V(2,0,1))
+    return 4;
+  else /* Everything 2.0 and later should be compatible. */
+    return 5;
+}
+
+/** Return the version number of the currently running version of Libevent.
+    See le_version_t for info on the format.
+ */
+static le_version_t
+tor_get_libevent_version(const char **v_out)
+{
+  const char *v;
+  le_version_t r;
+#if defined(HAVE_EVENT_GET_VERSION_NUMBER)
+  v = event_get_version();
+  r = event_get_version_number();
+#elif defined (HAVE_EVENT_GET_VERSION)
+  v = event_get_version();
+  r = tor_decode_libevent_version(v);
+#else
+  v = "pre-1.0c";
+  r = LE_OLD;
+#endif
+  if (v_out)
+    *v_out = v;
+  return r;
+}
+
+/** Return a string representation of the version of the currently running
+ * version of Libevent. */
+const char *
+tor_libevent_get_version_str(void)
+{
+#ifdef HAVE_EVENT_GET_VERSION
+  return event_get_version();
+#else
+  return "pre-1.0c";
+#endif
+}
+
+/**
+ * Compare the current Libevent method and version to a list of versions
+ * which are known not to work.  Warn the user as appropriate.
+ */
+void
+tor_check_libevent_version(const char *m, int server,
+                           const char **badness_out)
+{
+  int buggy = 0, iffy = 0, slow = 0, thread_unsafe = 0;
+  le_version_t version;
+  const char *v = NULL;
+  const char *badness = NULL;
+  const char *sad_os = "";
+
+  version = tor_get_libevent_version(&v);
+
+  /* XXX Would it be worthwhile disabling the methods that we know
+   * are buggy, rather than just warning about them and then proceeding
+   * to use them? If so, we should probably not wrap this whole thing
+   * in HAVE_EVENT_GET_VERSION and HAVE_EVENT_GET_METHOD. -RD */
+  /* XXXX The problem is that it's not trivial to get libevent to change it's
+   * method once it's initialized, and it's not trivial to tell what method it
+   * will use without initializing it.  I guess we could preemptively disable
+   * buggy libevent modes based on the version _before_ initializing it,
+   * though, but then there's no good way (afaict) to warn "I would have used
+   * kqueue, but instead I'm using select." -NM */
+  /* XXXX022 revist the above; it is fixable now. */
+  if (!strcmp(m, "kqueue")) {
+    if (version < V_OLD(1,1,'b'))
+      buggy = 1;
+  } else if (!strcmp(m, "epoll")) {
+    if (version < V(1,1,0))
+      iffy = 1;
+  } else if (!strcmp(m, "poll")) {
+    if (version < V_OLD(1,0,'e'))
+      buggy = 1;
+    if (version < V(1,1,0))
+      slow = 1;
+  } else if (!strcmp(m, "select")) {
+    if (version < V(1,1,0))
+      slow = 1;
+  } else if (!strcmp(m, "win32")) {
+    if (version < V_OLD(1,1,'b'))
+      buggy = 1;
+  }
+
+  /* Libevent versions before 1.3b do very badly on operating systems with
+   * user-space threading implementations. */
+#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__)
+  if (server && version < V_OLD(1,3,'b'))
+    thread_unsafe = 1;
+    sad_os = "BSD variants";
+  }
+#elif defined(__APPLE__) || defined(__darwin__)
+  if (server && version < V_OLD(1,3,'b'))
+    thread_unsafe = 1;
+    sad_os = "Mac OS X";
+  }
+#endif
+
+  if (thread_unsafe) {
+    log(LOG_WARN, LD_GENERAL,
+        "Libevent version %s often crashes when running a Tor server with %s. "
+        "Please use the latest version of libevent (1.3b or later)",v,sad_os);
+    badness = "BROKEN";
+  } else if (buggy) {
+    log(LOG_WARN, LD_GENERAL,
+        "There are serious bugs in using %s with libevent %s. "
+        "Please use the latest version of libevent.", m, v);
+    badness = "BROKEN";
+  } else if (iffy) {
+    log(LOG_WARN, LD_GENERAL,
+        "There are minor bugs in using %s with libevent %s. "
+        "You may want to use the latest version of libevent.", m, v);
+    badness = "BUGGY";
+  } else if (slow && server) {
+    log(LOG_WARN, LD_GENERAL,
+        "libevent %s can be very slow with %s. "
+        "When running a server, please use the latest version of libevent.",
+        v,m);
+    badness = "SLOW";
+  }
+
+  *badness_out = badness;
+}
+
+#if defined(LIBEVENT_VERSION)
+#define HEADER_VERSION LIBEVENT_VERSION
+#elif defined(_EVENT_VERSION)
+#define HEADER_VERSION _EVENT_VERSION
+#endif
+
+/** See whether the headers we were built against differ from the library we
+ * linked against so much that we're likely to crash.  If so, warn the
+ * user. */
+void
+tor_check_libevent_header_compatibility(void)
+{
+  (void) le_versions_compatibility;
+  (void) tor_decode_libevent_version;
+
+  /* In libevent versions before 2.0, it's hard to keep binary compatibility
+   * between upgrades, and unpleasant to detect when the version we compiled
+   * against is unlike the version we have linked against. Here's how. */
+#if defined(HEADER_VERSION) && defined(HAVE_EVENT_GET_VERSION)
+  /* We have a header-file version and a function-call version. Easy. */
+  if (strcmp(HEADER_VERSION, event_get_version())) {
+    le_version_t v1, v2;
+    int compat1 = -1, compat2 = -1;
+    int verybad;
+    v1 = tor_decode_libevent_version(HEADER_VERSION);
+    v2 = tor_decode_libevent_version(event_get_version());
+    compat1 = le_versions_compatibility(v1);
+    compat2 = le_versions_compatibility(v2);
+
+    verybad = compat1 != compat2;
+
+    log(verybad ? LOG_WARN : LOG_NOTICE,
+        LD_GENERAL, "We were compiled with headers from version %s "
+        "of Libevent, but we're using a Libevent library that says it's "
+        "version %s.", HEADER_VERSION, event_get_version());
+    if (verybad)
+      log_warn(LD_GENERAL, "This will almost certainly make Tor crash.");
+    else
+      log_info(LD_GENERAL, "I think these versions are binary-compatible.");
+  }
+#elif defined(HAVE_EVENT_GET_VERSION)
+  /* event_get_version but no _EVENT_VERSION.  We might be in 1.4.0-beta or
+     earlier, where that's normal.  To see whether we were compiled with an
+     earlier version, let's see whether the struct event defines MIN_HEAP_IDX.
+  */
+#ifdef HAVE_STRUCT_EVENT_MIN_HEAP_IDX
+  /* The header files are 1.4.0-beta or later. If the version is not
+   * 1.4.0-beta, we are incompatible. */
+  {
+    if (strcmp(event_get_version(), "1.4.0-beta")) {
+      log_warn(LD_GENERAL, "It's a little hard to tell, but you seem to have "
+               "Libevent 1.4.0-beta header files, whereas you have linked "
+               "against Libevent %s.  This will probably make Tor crash.",
+               event_get_version());
+    }
+  }
+#else
+  /* Our headers are 1.3e or earlier. If the library version is not 1.4.x or
+     later, we're probably fine. */
+  {
+    const char *v = event_get_version();
+    if ((v[0] == '1' && v[2] == '.' && v[3] > '3') || v[0] > '1') {
+      log_warn(LD_GENERAL, "It's a little hard to tell, but you seem to have "
+               "Libevent header file from 1.3e or earlier, whereas you have "
+               "linked against Libevent %s.  This will probably make Tor "
+               "crash.", event_get_version());
+    }
+  }
+#endif
+
+#elif defined(HEADER_VERSION)
+#warn "_EVENT_VERSION is defined but not get_event_version(): Libevent is odd."
+#else
+  /* Your libevent is ancient. */
+#endif
+}
diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h
index a95285f..5482c47 100644
--- a/src/common/compat_libevent.h
+++ b/src/common/compat_libevent.h
@@ -6,10 +6,12 @@
 
 #include "orconfig.h"
 
+struct event;
+struct event_base;
+
 #ifdef HAVE_EVENT2_EVENT_H
-#include <event2/event.h>
+#include <event2/util.h>
 #else
-#include <event.h>
 #define evutil_socket_t int
 #endif
 
@@ -34,6 +36,9 @@ void tor_event_free(struct event *ev);
 void tor_libevent_initialize(void);
 struct event_base *tor_libevent_get_base(void);
 const char *tor_libevent_get_method(void);
+void tor_check_libevent_version(const char *m, int server,
+                                const char **badness_out);
+void tor_check_libevent_header_compatibility(void);
+const char *tor_libevent_get_version_str(void);
 
 #endif
-
diff --git a/src/or/config.c b/src/or/config.c
index e5f27f9..bcabb67 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -706,20 +706,6 @@ static uint64_t config_parse_memunit(const char *s, int *ok);
 static int config_parse_interval(const char *s, int *ok);
 static void init_libevent(void);
 static int opt_streq(const char *s1, const char *s2);
-/** Versions of libevent. */
-typedef enum {
-  /* Note: we compare these, so it's important that "old" precede everything,
-   * and that "other" come last. */
-  LE_OLD=0, LE_10C, LE_10D, LE_10E, LE_11, LE_11A, LE_11B, LE_12, LE_12A,
-  LE_13, LE_13A, LE_13B, LE_13C, LE_13D, LE_13E,
-  LE_140, LE_141, LE_142, LE_143, LE_144, LE_145, LE_146, LE_147, LE_148,
-  LE_1499,
-  LE_OTHER
-} le_version_t;
-static le_version_t decode_libevent_version(const char *v, int *bincompat_out);
-#if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
-static void check_libevent_version(const char *m, int server);
-#endif
 
 /** Magic value for or_options_t. */
 #define OR_OPTIONS_MAGIC 9090909
@@ -4813,258 +4799,37 @@ config_parse_interval(const char *s, int *ok)
   return (int)r;
 }
 
-/* This is what passes for version detection on OSX.  We set
- * MACOSX_KQUEUE_IS_BROKEN to true iff we're on a version of OSX before
- * 10.4.0 (aka 1040). */
-#ifdef __APPLE__
-#ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
-#define MACOSX_KQUEUE_IS_BROKEN \
-  (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1040)
-#else
-#define MACOSX_KQUEUE_IS_BROKEN 0
-#endif
-#endif
-
 /**
  * Initialize the libevent library.
  */
 static void
 init_libevent(void)
 {
+  const char *badness=NULL;
+
   configure_libevent_logging();
   /* If the kernel complains that some method (say, epoll) doesn't
    * exist, we don't care about it, since libevent will cope.
    */
   suppress_libevent_log_msg("Function not implemented");
-#ifdef __APPLE__
-  if (MACOSX_KQUEUE_IS_BROKEN ||
-      decode_libevent_version(event_get_version(), NULL) < LE_11B) {
-    setenv("EVENT_NOKQUEUE","1",1);
-  }
-#endif
 
-  /* In libevent versions before 2.0, it's hard to keep binary compatibility
-   * between upgrades, and unpleasant to detect when the version we compiled
-   * against is unlike the version we have linked against. Here's how. */
-#if defined(_EVENT_VERSION) && defined(HAVE_EVENT_GET_VERSION)
-  /* We have a header-file version and a function-call version. Easy. */
-  if (strcmp(_EVENT_VERSION, event_get_version())) {
-    int compat1 = -1, compat2 = -1;
-    int verybad, prettybad ;
-    decode_libevent_version(_EVENT_VERSION, &compat1);
-    decode_libevent_version(event_get_version(), &compat2);
-    verybad = compat1 != compat2;
-    prettybad = (compat1 == -1 || compat2 == -1) && compat1 != compat2;
-
-    log(verybad ? LOG_WARN : (prettybad ? LOG_NOTICE : LOG_INFO),
-        LD_GENERAL, "We were compiled with headers from version %s "
-        "of Libevent, but we're using a Libevent library that says it's "
-        "version %s.", _EVENT_VERSION, event_get_version());
-    if (verybad)
-      log_warn(LD_GENERAL, "This will almost certainly make Tor crash.");
-    else if (prettybad)
-      log_notice(LD_GENERAL, "If Tor crashes, this might be why.");
-    else
-      log_info(LD_GENERAL, "I think these versions are binary-compatible.");
-  }
-#elif defined(HAVE_EVENT_GET_VERSION)
-  /* event_get_version but no _EVENT_VERSION.  We might be in 1.4.0-beta or
-     earlier, where that's normal.  To see whether we were compiled with an
-     earlier version, let's see whether the struct event defines MIN_HEAP_IDX.
-  */
-#ifdef HAVE_STRUCT_EVENT_MIN_HEAP_IDX
-  /* The header files are 1.4.0-beta or later. If the version is not
-   * 1.4.0-beta, we are incompatible. */
-  {
-    if (strcmp(event_get_version(), "1.4.0-beta")) {
-      log_warn(LD_GENERAL, "It's a little hard to tell, but you seem to have "
-               "Libevent 1.4.0-beta header files, whereas you have linked "
-               "against Libevent %s.  This will probably make Tor crash.",
-               event_get_version());
-    }
-  }
-#else
-  /* Our headers are 1.3e or earlier. If the library version is not 1.4.x or
-     later, we're probably fine. */
-  {
-    const char *v = event_get_version();
-    if ((v[0] == '1' && v[2] == '.' && v[3] > '3') || v[0] > '1') {
-      log_warn(LD_GENERAL, "It's a little hard to tell, but you seem to have "
-               "Libevent header file from 1.3e or earlier, whereas you have "
-               "linked against Libevent %s.  This will probably make Tor "
-               "crash.", event_get_version());
-    }
-  }
-#endif
-
-#elif defined(_EVENT_VERSION)
-#warn "_EVENT_VERSION is defined but not get_event_version(): Libevent is odd."
-#else
-  /* Your libevent is ancient. */
-#endif
+  tor_check_libevent_header_compatibility();
 
   tor_libevent_initialize();
 
   suppress_libevent_log_msg(NULL);
-#if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
-  /* Making this a NOTICE for now so we can link bugs to a libevent versions
-   * or methods better. */
-  log(LOG_NOTICE, LD_GENERAL,
-      "Initialized libevent version %s using method %s. Good.",
-      event_get_version(), tor_libevent_get_method());
-  check_libevent_version(tor_libevent_get_method(),
-                         get_options()->ORPort != 0);
-#else
-  log(LOG_NOTICE, LD_GENERAL,
-      "Initialized old libevent (version 1.0b or earlier).");
-  log(LOG_WARN, LD_GENERAL,
-      "You have a *VERY* old version of libevent.  It is likely to be buggy; "
-      "please build Tor with a more recent version.");
-#endif
-}
-
-/** Table mapping return value of event_get_version() to le_version_t. */
-static const struct {
-  const char *name; le_version_t version; int bincompat;
-} le_version_table[] = {
-  /* earlier versions don't have get_version. */
-  { "1.0c", LE_10C, 1},
-  { "1.0d", LE_10D, 1},
-  { "1.0e", LE_10E, 1},
-  { "1.1",  LE_11,  1 },
-  { "1.1a", LE_11A, 1 },
-  { "1.1b", LE_11B, 1 },
-  { "1.2",  LE_12,  1 },
-  { "1.2a", LE_12A, 1 },
-  { "1.3",  LE_13,  1 },
-  { "1.3a", LE_13A, 1 },
-  { "1.3b", LE_13B, 1 },
-  { "1.3c", LE_13C, 1 },
-  { "1.3d", LE_13D, 1 },
-  { "1.3e", LE_13E, 1 },
-  { "1.4.0-beta", LE_140, 2 },
-  { "1.4.1-beta", LE_141, 2 },
-  { "1.4.2-rc",   LE_142, 2 },
-  { "1.4.3-stable", LE_143, 2 },
-  { "1.4.4-stable", LE_144, 2 },
-  { "1.4.5-stable", LE_145, 2 },
-  { "1.4.6-stable", LE_146, 2 },
-  { "1.4.7-stable", LE_147, 2 },
-  { "1.4.8-stable", LE_148, 2 },
-  { "1.4.99-trunk", LE_1499, 3 },
-  { NULL, LE_OTHER, 0 }
-};
-
-/** Return the le_version_t for the current version of libevent.  If the
- * version is very new, return LE_OTHER.  If the version is so old that it
- * doesn't support event_get_version(), return LE_OLD. */
-static le_version_t
-decode_libevent_version(const char *v, int *bincompat_out)
-{
-  int i;
-  for (i=0; le_version_table[i].name; ++i) {
-    if (!strcmp(le_version_table[i].name, v)) {
-      if (bincompat_out)
-        *bincompat_out = le_version_table[i].bincompat;
-      return le_version_table[i].version;
-    }
-  }
-  if (v[0] != '1' && bincompat_out)
-    *bincompat_out = 100;
-  else if (!strcmpstart(v, "1.4") && bincompat_out)
-    *bincompat_out = 2;
-  return LE_OTHER;
-}
 
-#if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
-/**
- * Compare the given libevent method and version to a list of versions
- * which are known not to work.  Warn the user as appropriate.
- */
-static void
-check_libevent_version(const char *m, int server)
-{
-  int buggy = 0, iffy = 0, slow = 0, thread_unsafe = 0;
-  le_version_t version;
-  const char *v = event_get_version();
-  const char *badness = NULL;
-  const char *sad_os = "";
-
-  version = decode_libevent_version(v, NULL);
-
-  /* XXX Would it be worthwhile disabling the methods that we know
-   * are buggy, rather than just warning about them and then proceeding
-   * to use them? If so, we should probably not wrap this whole thing
-   * in HAVE_EVENT_GET_VERSION and HAVE_EVENT_GET_METHOD. -RD */
-  /* XXXX The problem is that it's not trivial to get libevent to change it's
-   * method once it's initialized, and it's not trivial to tell what method it
-   * will use without initializing it.  I guess we could preemptively disable
-   * buggy libevent modes based on the version _before_ initializing it,
-   * though, but then there's no good way (afaict) to warn "I would have used
-   * kqueue, but instead I'm using select." -NM */
-  if (!strcmp(m, "kqueue")) {
-    if (version < LE_11B)
-      buggy = 1;
-  } else if (!strcmp(m, "epoll")) {
-    if (version < LE_11)
-      iffy = 1;
-  } else if (!strcmp(m, "poll")) {
-    if (version < LE_10E)
-      buggy = 1;
-    else if (version < LE_11)
-      slow = 1;
-  } else if (!strcmp(m, "select")) {
-    if (version < LE_11)
-      slow = 1;
-  } else if (!strcmp(m, "win32")) {
-    if (version < LE_11B)
-      buggy = 1;
-  }
-
-  /* Libevent versions before 1.3b do very badly on operating systems with
-   * user-space threading implementations. */
-#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__)
-  if (server && version < LE_13B) {
-    thread_unsafe = 1;
-    sad_os = "BSD variants";
-  }
-#elif defined(__APPLE__) || defined(__darwin__)
-  if (server && version < LE_13B) {
-    thread_unsafe = 1;
-    sad_os = "Mac OS X";
-  }
-#endif
-
-  if (thread_unsafe) {
-    log(LOG_WARN, LD_GENERAL,
-        "Libevent version %s often crashes when running a Tor server with %s. "
-        "Please use the latest version of libevent (1.3b or later)",v,sad_os);
-    badness = "BROKEN";
-  } else if (buggy) {
-    log(LOG_WARN, LD_GENERAL,
-        "There are serious bugs in using %s with libevent %s. "
-        "Please use the latest version of libevent.", m, v);
-    badness = "BROKEN";
-  } else if (iffy) {
-    log(LOG_WARN, LD_GENERAL,
-        "There are minor bugs in using %s with libevent %s. "
-        "You may want to use the latest version of libevent.", m, v);
-    badness = "BUGGY";
-  } else if (slow && server) {
-    log(LOG_WARN, LD_GENERAL,
-        "libevent %s can be very slow with %s. "
-        "When running a server, please use the latest version of libevent.",
-        v,m);
-    badness = "SLOW";
-  }
+  tor_check_libevent_version(tor_libevent_get_method(),
+                             get_options()->ORPort != 0,
+                             &badness);
   if (badness) {
+    const char *v = tor_libevent_get_version_str();
+    const char *m = tor_libevent_get_method();
     control_event_general_status(LOG_WARN,
         "BAD_LIBEVENT VERSION=%s METHOD=%s BADNESS=%s RECOVERED=NO",
                                  v, m, badness);
   }
-
 }
-#endif
 
 /** Return the persistent state struct for this Tor. */
 or_state_t *
diff --git a/src/or/or.h b/src/or/or.h
index 59425fa..e4989fc 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -93,6 +93,12 @@
 #include "address.h"
 #include "compat_libevent.h"
 
+#ifdef HAVE_EVENT2_EVENT_H
+#include <event2/event.h>
+#else
+#include <event.h>
+#endif
+
 /* These signals are defined to help control_signal_act work.
  */
 #ifndef SIGHUP
-- 
1.5.6.5




More information about the tor-commits mailing list