Move the Libvent setup logic into compat_libevent from config.

This has been some pretty ugly and voodoo-laden code.  I've tried to
clean it up a bit, but more work probably remains.
This commit is contained in:
Nick Mathewson 2009-06-04 03:16:26 -04:00
parent e5b88dc83f
commit c0af3cdfb6
5 changed files with 328 additions and 247 deletions

View File

@ -273,7 +273,7 @@ save_CPPFLAGS="$CPPFLAGS"
LIBS="-levent $TOR_LIB_WS32 $LIBS" LIBS="-levent $TOR_LIB_WS32 $LIBS"
LDFLAGS="$TOR_LDFLAGS_libevent $LDFLAGS" LDFLAGS="$TOR_LDFLAGS_libevent $LDFLAGS"
CPPFLAGS="$TOR_CPPFLAGS_libevent $CPPFLAGS" 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], , , AC_CHECK_MEMBERS([struct event.min_heap_idx], , ,
[#include <event.h> [#include <event.h>
]) ])

View File

@ -23,6 +23,21 @@
#include <event.h> #include <event.h>
#endif #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 #ifdef HAVE_EVENT_SET_LOG_CALLBACK
/** A string which, if it appears in a libevent log, should be ignored. */ /** A string which, if it appears in a libevent log, should be ignored. */
static const char *suppress_msg = NULL; 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. */ /** Global event base for use by the main thread. */
struct event_base *the_event_base = NULL; 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. */ /** Initialize the Libevent library and set up the event base. */
void void
tor_libevent_initialize(void) tor_libevent_initialize(void)
{ {
tor_assert(the_event_base == NULL); 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 #ifdef HAVE_EVENT2_EVENT_H
the_event_base = event_base_new(); the_event_base = event_base_new();
#else #else
the_event_base = event_init(); the_event_base = event_init();
#endif #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. */ /** Return the current Libevent event base that we're set up to use. */
@ -151,3 +201,258 @@ tor_libevent_get_method(void)
#endif #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
}

View File

@ -6,10 +6,12 @@
#include "orconfig.h" #include "orconfig.h"
struct event;
struct event_base;
#ifdef HAVE_EVENT2_EVENT_H #ifdef HAVE_EVENT2_EVENT_H
#include <event2/event.h> #include <event2/util.h>
#else #else
#include <event.h>
#define evutil_socket_t int #define evutil_socket_t int
#endif #endif
@ -34,6 +36,9 @@ void tor_event_free(struct event *ev);
void tor_libevent_initialize(void); void tor_libevent_initialize(void);
struct event_base *tor_libevent_get_base(void); struct event_base *tor_libevent_get_base(void);
const char *tor_libevent_get_method(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 #endif

View File

@ -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 int config_parse_interval(const char *s, int *ok);
static void init_libevent(void); static void init_libevent(void);
static int opt_streq(const char *s1, const char *s2); 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. */ /** Magic value for or_options_t. */
#define OR_OPTIONS_MAGIC 9090909 #define OR_OPTIONS_MAGIC 9090909
@ -4813,258 +4799,37 @@ config_parse_interval(const char *s, int *ok)
return (int)r; 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. * Initialize the libevent library.
*/ */
static void static void
init_libevent(void) init_libevent(void)
{ {
const char *badness=NULL;
configure_libevent_logging(); configure_libevent_logging();
/* If the kernel complains that some method (say, epoll) doesn't /* If the kernel complains that some method (say, epoll) doesn't
* exist, we don't care about it, since libevent will cope. * exist, we don't care about it, since libevent will cope.
*/ */
suppress_libevent_log_msg("Function not implemented"); 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 tor_check_libevent_header_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_libevent_initialize(); tor_libevent_initialize();
suppress_libevent_log_msg(NULL); 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. */ tor_check_libevent_version(tor_libevent_get_method(),
static const struct { get_options()->ORPort != 0,
const char *name; le_version_t version; int bincompat; &badness);
} 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";
}
if (badness) { if (badness) {
const char *v = tor_libevent_get_version_str();
const char *m = tor_libevent_get_method();
control_event_general_status(LOG_WARN, control_event_general_status(LOG_WARN,
"BAD_LIBEVENT VERSION=%s METHOD=%s BADNESS=%s RECOVERED=NO", "BAD_LIBEVENT VERSION=%s METHOD=%s BADNESS=%s RECOVERED=NO",
v, m, badness); v, m, badness);
} }
} }
#endif
/** Return the persistent state struct for this Tor. */ /** Return the persistent state struct for this Tor. */
or_state_t * or_state_t *

View File

@ -93,6 +93,12 @@
#include "address.h" #include "address.h"
#include "compat_libevent.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. /* These signals are defined to help control_signal_act work.
*/ */
#ifndef SIGHUP #ifndef SIGHUP