diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | configure.in | 4 | ||||
-rw-r--r-- | src/or/config.c | 129 |
3 files changed, 110 insertions, 28 deletions
@@ -6,6 +6,11 @@ Changes in version 0.2.1.11-alpha - 2009-01-?? keys in those obsolete descriptors when building circuits. Bugfix on 0.2.0.x. Fixes bug 887. + o Minor features: + - Try to make sure that the version of Libevent we're running with + is binary-compatible with the one we built with. May address bug + 897 and others. + o Minor bugfixes: - Make outbound DNS packets respect the OutboundBindAddress setting. Fixes the bug part of bug 798. Bugfix on 0.1.2.2-alpha. diff --git a/configure.in b/configure.in index aa59e776a5..8cd4428853 100644 --- a/configure.in +++ b/configure.in @@ -264,6 +264,10 @@ 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) +AC_CHECK_MEMBERS([struct event.min_heap_idx], , , +[#include <event.h> +]) + LIBS="$save_LIBS" LDFLAGS="$save_LDFLAGS" CPPFLAGS="$save_CPPFLAGS" diff --git a/src/or/config.c b/src/or/config.c index f733c362f7..02b9793737 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -702,10 +702,12 @@ 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_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(void); +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 @@ -4741,10 +4743,71 @@ init_libevent(void) */ suppress_libevent_log_msg("Function not implemented"); #ifdef __APPLE__ - if (decode_libevent_version() < LE_11B) { + if (decode_libevent_version(event_get_version()) < 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 + event_init(); suppress_libevent_log_msg(NULL); #if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD) @@ -4763,44 +4826,60 @@ init_libevent(void) #endif } -#if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD) /** Table mapping return value of event_get_version() to le_version_t. */ static const struct { - const char *name; le_version_t version; + const char *name; le_version_t version; int bincompat; } le_version_table[] = { /* earlier versions don't have get_version. */ - { "1.0c", LE_10C }, - { "1.0d", LE_10D }, - { "1.0e", LE_10E }, - { "1.1", LE_11 }, - { "1.1a", LE_11A }, - { "1.1b", LE_11B }, - { "1.2", LE_12 }, - { "1.2a", LE_12A }, - { "1.3", LE_13 }, - { "1.3a", LE_13A }, - { "1.3b", LE_13B }, - { "1.3c", LE_13C }, - { "1.3d", LE_13D }, - { NULL, LE_OTHER } + { "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(void) +decode_libevent_version(const char *v, int *bincompat_out) { - const char *v = event_get_version(); 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. @@ -4814,7 +4893,7 @@ check_libevent_version(const char *m, int server) const char *badness = NULL; const char *sad_os = ""; - version = decode_libevent_version(); + 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 @@ -4888,12 +4967,6 @@ check_libevent_version(const char *m, int server) } } -#else -static le_version_t -decode_libevent_version(void) -{ - return LE_OLD; -} #endif /** Return the persistent state struct for this Tor. */ |