mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Raise libevent dependency to 2.0.10-stable or newer
Only some very ancient distributions don't ship with Libevent 2 anymore, even the oldest supported Ubuntu LTS version has it. This allows us to get rid of a lot of compat code.
This commit is contained in:
@@ -19,15 +19,11 @@
|
||||
#include "util.h"
|
||||
#include "torlog.h"
|
||||
|
||||
#ifdef HAVE_EVENT2_EVENT_H
|
||||
#include <event2/event.h>
|
||||
#include <event2/thread.h>
|
||||
#ifdef USE_BUFFEREVENTS
|
||||
#include <event2/bufferevent.h>
|
||||
#endif
|
||||
#else
|
||||
#include <event.h>
|
||||
#endif
|
||||
|
||||
/** A string which, if it appears in a libevent log, should be ignored. */
|
||||
static const char *suppress_msg = NULL;
|
||||
@@ -69,6 +65,7 @@ configure_libevent_logging(void)
|
||||
{
|
||||
event_set_log_callback(libevent_logging_callback);
|
||||
}
|
||||
|
||||
/** Ignore any libevent log message that contains <b>msg</b>. */
|
||||
void
|
||||
suppress_libevent_log_msg(const char *msg)
|
||||
@@ -76,44 +73,6 @@ suppress_libevent_log_msg(const char *msg)
|
||||
suppress_msg = msg;
|
||||
}
|
||||
|
||||
#ifndef HAVE_EVENT2_EVENT_H
|
||||
/** Work-alike replacement for event_new() on pre-Libevent-2.0 systems. */
|
||||
struct event *
|
||||
tor_event_new(struct event_base *base, int sock, short what,
|
||||
void (*cb)(int, short, void *), void *arg)
|
||||
{
|
||||
struct event *e = tor_malloc_zero(sizeof(struct event));
|
||||
event_set(e, sock, what, cb, arg);
|
||||
if (! base)
|
||||
base = tor_libevent_get_base();
|
||||
event_base_set(base, e);
|
||||
return e;
|
||||
}
|
||||
/** Work-alike replacement for evtimer_new() on pre-Libevent-2.0 systems. */
|
||||
struct event *
|
||||
tor_evtimer_new(struct event_base *base,
|
||||
void (*cb)(int, short, void *), void *arg)
|
||||
{
|
||||
return tor_event_new(base, -1, 0, cb, arg);
|
||||
}
|
||||
/** Work-alike replacement for evsignal_new() on pre-Libevent-2.0 systems. */
|
||||
struct event *
|
||||
tor_evsignal_new(struct event_base * base, int sig,
|
||||
void (*cb)(int, short, void *), void *arg)
|
||||
{
|
||||
return tor_event_new(base, sig, EV_SIGNAL|EV_PERSIST, cb, arg);
|
||||
}
|
||||
/** Work-alike replacement for event_free() on pre-Libevent-2.0 systems,
|
||||
* except tolerate tor_event_free(NULL). */
|
||||
void
|
||||
tor_event_free(struct event *ev)
|
||||
{
|
||||
if (ev == NULL)
|
||||
return;
|
||||
event_del(ev);
|
||||
tor_free(ev);
|
||||
}
|
||||
#else
|
||||
/* Wrapper for event_free() that tolerates tor_event_free(NULL) */
|
||||
void
|
||||
tor_event_free(struct event *ev)
|
||||
@@ -122,7 +81,6 @@ tor_event_free(struct event *ev)
|
||||
return;
|
||||
event_free(ev);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Global event base for use by the main thread. */
|
||||
static struct event_base *the_event_base = NULL;
|
||||
@@ -158,7 +116,6 @@ tor_libevent_initialize(tor_libevent_cfg *torcfg)
|
||||
/* some paths below don't use torcfg, so avoid unused variable warnings */
|
||||
(void)torcfg;
|
||||
|
||||
#ifdef HAVE_EVENT2_EVENT_H
|
||||
{
|
||||
int attempts = 0;
|
||||
int using_threads;
|
||||
@@ -190,16 +147,12 @@ tor_libevent_initialize(tor_libevent_cfg *torcfg)
|
||||
event_config_set_flag(cfg, EVENT_BASE_FLAG_NOLOCK);
|
||||
}
|
||||
|
||||
#if defined(LIBEVENT_VERSION_NUMBER) && LIBEVENT_VERSION_NUMBER >= V(2,0,7)
|
||||
if (torcfg->num_cpus > 0)
|
||||
event_config_set_num_cpus_hint(cfg, torcfg->num_cpus);
|
||||
#endif
|
||||
|
||||
#if LIBEVENT_VERSION_NUMBER >= V(2,0,9)
|
||||
/* We can enable changelist support with epoll, since we don't give
|
||||
* Libevent any dup'd fds. This lets us avoid some syscalls. */
|
||||
event_config_set_flag(cfg, EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST);
|
||||
#endif
|
||||
|
||||
the_event_base = event_base_new_with_config(cfg);
|
||||
|
||||
@@ -223,9 +176,6 @@ tor_libevent_initialize(tor_libevent_cfg *torcfg)
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
#else
|
||||
the_event_base = event_init();
|
||||
#endif
|
||||
|
||||
if (!the_event_base) {
|
||||
/* LCOV_EXCL_START */
|
||||
@@ -255,62 +205,7 @@ tor_libevent_get_base, (void))
|
||||
const char *
|
||||
tor_libevent_get_method(void)
|
||||
{
|
||||
#ifdef HAVE_EVENT2_EVENT_H
|
||||
return event_base_get_method(the_event_base);
|
||||
#else
|
||||
return event_get_method();
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Return the le_version_t for the version of libevent specified in the
|
||||
* string <b>v</b>. If the version is very new or uses an unrecognized
|
||||
* version, format, return LE_OTHER. */
|
||||
STATIC le_version_t
|
||||
tor_decode_libevent_version(const char *v)
|
||||
{
|
||||
unsigned major, minor, patchlevel;
|
||||
char c, e, extra;
|
||||
int fields;
|
||||
|
||||
/* Try the new preferred "1.4.11-stable" format.
|
||||
* Also accept "1.4.14b-stable". */
|
||||
fields = tor_sscanf(v, "%u.%u.%u%c%c", &major, &minor, &patchlevel, &c, &e);
|
||||
if (fields == 3 ||
|
||||
((fields == 4 || fields == 5 ) && (c == '-' || c == '_')) ||
|
||||
(fields == 5 && TOR_ISALPHA(c) && (e == '-' || e == '_'))) {
|
||||
return V(major,minor,patchlevel);
|
||||
}
|
||||
|
||||
/* Try the old "1.3e" format. */
|
||||
fields = tor_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 a string representation of the version of the currently running
|
||||
@@ -321,101 +216,14 @@ tor_libevent_get_version_str(void)
|
||||
return event_get_version();
|
||||
}
|
||||
|
||||
#if defined(LIBEVENT_VERSION)
|
||||
#define HEADER_VERSION LIBEVENT_VERSION
|
||||
#elif defined(_EVENT_VERSION)
|
||||
#define HEADER_VERSION _EVENT_VERSION
|
||||
#endif
|
||||
|
||||
/** Return a string representation of the version of Libevent that was used
|
||||
* at compilation time. */
|
||||
const char *
|
||||
tor_libevent_get_header_version_str(void)
|
||||
{
|
||||
return HEADER_VERSION;
|
||||
return LIBEVENT_VERSION;
|
||||
}
|
||||
|
||||
/** 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)
|
||||
/* 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;
|
||||
|
||||
tor_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.");
|
||||
}
|
||||
#else
|
||||
/* 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
|
||||
|
||||
/* Your libevent is ancient. */
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
If possible, we're going to try to use Libevent's periodic timer support,
|
||||
since it does a pretty good job of making sure that periodic events get
|
||||
called exactly M seconds apart, rather than starting each one exactly M
|
||||
seconds after the time that the last one was run.
|
||||
*/
|
||||
#ifdef HAVE_EVENT2_EVENT_H
|
||||
#define HAVE_PERIODIC
|
||||
#define PERIODIC_FLAGS EV_PERSIST
|
||||
#else
|
||||
#define PERIODIC_FLAGS 0
|
||||
#endif
|
||||
|
||||
/** Represents a timer that's run every N microseconds by Libevent. */
|
||||
struct periodic_timer_t {
|
||||
/** Underlying event used to implement this periodic event. */
|
||||
@@ -424,11 +232,6 @@ struct periodic_timer_t {
|
||||
void (*cb)(struct periodic_timer_t *, void *);
|
||||
/** User-supplied data for the callback */
|
||||
void *data;
|
||||
#ifndef HAVE_PERIODIC
|
||||
/** If Libevent doesn't know how to invoke events every N microseconds,
|
||||
* we'll need to remember the timeout interval here. */
|
||||
struct timeval tv;
|
||||
#endif
|
||||
};
|
||||
|
||||
/** Libevent callback to implement a periodic event. */
|
||||
@@ -438,10 +241,6 @@ periodic_timer_cb(evutil_socket_t fd, short what, void *arg)
|
||||
periodic_timer_t *timer = arg;
|
||||
(void) what;
|
||||
(void) fd;
|
||||
#ifndef HAVE_PERIODIC
|
||||
/** reschedule the event as needed. */
|
||||
event_add(timer->ev, &timer->tv);
|
||||
#endif
|
||||
timer->cb(timer, timer->data);
|
||||
}
|
||||
|
||||
@@ -459,16 +258,13 @@ periodic_timer_new(struct event_base *base,
|
||||
tor_assert(tv);
|
||||
tor_assert(cb);
|
||||
timer = tor_malloc_zero(sizeof(periodic_timer_t));
|
||||
if (!(timer->ev = tor_event_new(base, -1, PERIODIC_FLAGS,
|
||||
if (!(timer->ev = tor_event_new(base, -1, EV_PERSIST,
|
||||
periodic_timer_cb, timer))) {
|
||||
tor_free(timer);
|
||||
return NULL;
|
||||
}
|
||||
timer->cb = cb;
|
||||
timer->data = data;
|
||||
#ifndef HAVE_PERIODIC
|
||||
memcpy(&timer->tv, tv, sizeof(struct timeval));
|
||||
#endif
|
||||
event_add(timer->ev, (struct timeval *)tv); /*drop const for old libevent*/
|
||||
return timer;
|
||||
}
|
||||
@@ -539,7 +335,6 @@ int
|
||||
tor_init_libevent_rng(void)
|
||||
{
|
||||
int rv = 0;
|
||||
#ifdef HAVE_EVUTIL_SECURE_RNG_INIT
|
||||
char buf[256];
|
||||
if (evutil_secure_rng_init() < 0) {
|
||||
rv = -1;
|
||||
@@ -547,7 +342,6 @@ tor_init_libevent_rng(void)
|
||||
crypto_rand(buf, 32);
|
||||
evutil_secure_rng_add_bytes(buf, 32);
|
||||
evutil_secure_rng_get_bytes(buf, sizeof(buf));
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,32 +15,17 @@ struct ev_token_bucket_cfg;
|
||||
struct bufferevent_rate_limit_group;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_EVENT2_EVENT_H
|
||||
#include <event2/util.h>
|
||||
#elif !defined(EVUTIL_SOCKET_DEFINED)
|
||||
#define EVUTIL_SOCKET_DEFINED
|
||||
#define evutil_socket_t int
|
||||
#endif
|
||||
|
||||
void configure_libevent_logging(void);
|
||||
void suppress_libevent_log_msg(const char *msg);
|
||||
|
||||
#ifdef HAVE_EVENT2_EVENT_H
|
||||
#define tor_event_new event_new
|
||||
#define tor_evtimer_new evtimer_new
|
||||
#define tor_evsignal_new evsignal_new
|
||||
#define tor_evdns_add_server_port(sock, tcp, cb, data) \
|
||||
evdns_add_server_port_with_base(tor_libevent_get_base(), \
|
||||
(sock),(tcp),(cb),(data));
|
||||
#else
|
||||
struct event *tor_event_new(struct event_base * base, evutil_socket_t sock,
|
||||
short what, void (*cb)(evutil_socket_t, short, void *), void *arg);
|
||||
struct event *tor_evtimer_new(struct event_base * base,
|
||||
void (*cb)(evutil_socket_t, short, void *), void *arg);
|
||||
struct event *tor_evsignal_new(struct event_base * base, int sig,
|
||||
void (*cb)(evutil_socket_t, short, void *), void *arg);
|
||||
#define tor_evdns_add_server_port evdns_add_server_port
|
||||
#endif
|
||||
|
||||
void tor_event_free(struct event *ev);
|
||||
|
||||
@@ -99,9 +84,7 @@ void tor_gettimeofday_cached_monotonic(struct timeval *tv);
|
||||
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.
|
||||
2.0.1 or later.
|
||||
*/
|
||||
typedef uint32_t le_version_t;
|
||||
|
||||
@@ -109,23 +92,10 @@ typedef uint32_t le_version_t;
|
||||
/** Macros: returns the number of a libevent version as a le_version_t */
|
||||
#define V(major, minor, patch) \
|
||||
(((major) << 24) | ((minor) << 16) | ((patch) << 8))
|
||||
#define V_OLD(major, minor, patch) \
|
||||
V((major), (minor), (patch)-'a'+1)
|
||||
/** @} */
|
||||
|
||||
/** Represetns a version of libevent so old we can't figure out what version
|
||||
* it is. */
|
||||
#define LE_OLD V(0,0,0)
|
||||
/** Represents a version of libevent so weird we can't figure out what version
|
||||
* it is. */
|
||||
#define LE_OTHER V(0,0,99)
|
||||
|
||||
STATIC void
|
||||
libevent_logging_callback(int severity, const char *msg);
|
||||
STATIC le_version_t
|
||||
tor_decode_libevent_version(const char *v);
|
||||
STATIC int
|
||||
le_versions_compatibility(le_version_t v);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,11 +10,7 @@
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#ifdef HAVE_EVENT2_EVENT_H
|
||||
#include <event2/event.h>
|
||||
#else
|
||||
#include <event.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
@@ -164,11 +160,7 @@ tor_validate_process_specifier(const char *process_spec,
|
||||
}
|
||||
|
||||
/* XXXX we should use periodic_timer_new() for this stuff */
|
||||
#ifdef HAVE_EVENT2_EVENT_H
|
||||
#define PERIODIC_TIMER_FLAGS EV_PERSIST
|
||||
#else
|
||||
#define PERIODIC_TIMER_FLAGS (0)
|
||||
#endif
|
||||
|
||||
/* DOCDOC poll_interval_tv */
|
||||
static struct timeval poll_interval_tv = {15, 0};
|
||||
@@ -331,10 +323,6 @@ tor_process_monitor_poll_cb(evutil_socket_t unused1, short unused2,
|
||||
|
||||
if (its_dead_jim) {
|
||||
procmon->cb(procmon->cb_arg);
|
||||
#ifndef HAVE_EVENT2_EVENT_H
|
||||
} else {
|
||||
evtimer_add(procmon->e, &poll_interval_tv);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -38,11 +38,7 @@
|
||||
#include "torlog.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifdef HAVE_EVENT2_EVENT_H
|
||||
#include <event2/event.h>
|
||||
#else
|
||||
#include <event.h>
|
||||
#endif
|
||||
|
||||
struct timeout_cb {
|
||||
timer_cb_fn_t cb;
|
||||
|
||||
Reference in New Issue
Block a user