1 /* Copyright (c) 2009-2010, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
5 * \file compat_libevent.c
6 * \brief Wrappers to handle porting between different versions of libevent.
8 * In an ideal world, we'd just use Libevent 2.0 from now on. But as of June
9 * 2009, Libevent 2.0 is still in alpha, and we will have old versions of
10 * Libevent for the forseeable future.
15 #include "compat_libevent.h"
20 #ifdef HAVE_EVENT2_EVENT_H
21 #include <event2/event.h>
26 /** A number representing a version of Libevent.
28 This is a 4-byte number, with the first three bytes representing the
29 major, minor, and patchlevel respectively of the library. The fourth
32 This is equivalent to the format of LIBEVENT_VERSION_NUMBER on Libevent
33 2.0.1 or later. For versions of Libevent before 1.4.0, which followed the
34 format of "1.0, 1.0a, 1.0b", we define 1.0 to be equivalent to 1.0.0, 1.0a
35 to be equivalent to 1.0.1, and so on.
37 typedef uint32_t le_version_t
;
39 /* Macros: returns the number of a libevent version. */
40 #define V(major, minor, patch) \
41 (((major) << 24) | ((minor) << 16) | ((patch) << 8))
42 #define V_OLD(major, minor, patch) \
43 V((major), (minor), (patch)-'a'+1)
45 #define LE_OLD V(0,0,0)
46 #define LE_OTHER V(0,0,99)
48 static le_version_t
tor_get_libevent_version(const char **v_out
);
50 #ifdef HAVE_EVENT_SET_LOG_CALLBACK
51 /** A string which, if it appears in a libevent log, should be ignored. */
52 static const char *suppress_msg
= NULL
;
53 /** Callback function passed to event_set_log() so we can intercept
54 * log messages from libevent. */
56 libevent_logging_callback(int severity
, const char *msg
)
60 if (suppress_msg
&& strstr(msg
, suppress_msg
))
62 n
= strlcpy(buf
, msg
, sizeof(buf
));
63 if (n
&& n
< sizeof(buf
) && buf
[n
-1] == '\n') {
67 case _EVENT_LOG_DEBUG
:
68 log(LOG_DEBUG
, LD_NET
, "Message from libevent: %s", buf
);
71 log(LOG_INFO
, LD_NET
, "Message from libevent: %s", buf
);
74 log(LOG_WARN
, LD_GENERAL
, "Warning from libevent: %s", buf
);
77 log(LOG_ERR
, LD_GENERAL
, "Error from libevent: %s", buf
);
80 log(LOG_WARN
, LD_GENERAL
, "Message [%d] from libevent: %s",
85 /** Set hook to intercept log messages from libevent. */
87 configure_libevent_logging(void)
89 event_set_log_callback(libevent_logging_callback
);
91 /** Ignore any libevent log message that contains <b>msg</b>. */
93 suppress_libevent_log_msg(const char *msg
)
99 configure_libevent_logging(void)
103 suppress_libevent_log_msg(const char *msg
)
109 #ifndef HAVE_EVENT2_EVENT_H
110 /** Work-alike replacement for event_new() on pre-Libevent-2.0 systems. */
112 tor_event_new(struct event_base
*base
, int sock
, short what
,
113 void (*cb
)(int, short, void *), void *arg
)
115 struct event
*e
= tor_malloc_zero(sizeof(struct event
));
116 event_set(e
, sock
, what
, cb
, arg
);
118 base
= tor_libevent_get_base();
119 event_base_set(base
, e
);
122 /** Work-alike replacement for evtimer_new() on pre-Libevent-2.0 systems. */
124 tor_evtimer_new(struct event_base
*base
,
125 void (*cb
)(int, short, void *), void *arg
)
127 return tor_event_new(base
, -1, 0, cb
, arg
);
129 /** Work-alike replacement for evsignal_new() on pre-Libevent-2.0 systems. */
131 tor_evsignal_new(struct event_base
* base
, int sig
,
132 void (*cb
)(int, short, void *), void *arg
)
134 return tor_event_new(base
, sig
, EV_SIGNAL
|EV_PERSIST
, cb
, arg
);
136 /** Work-alike replacement for event_free() on pre-Libevent-2.0 systems. */
138 tor_event_free(struct event
*ev
)
145 /** Global event base for use by the main thread. */
146 struct event_base
*the_event_base
= NULL
;
148 /* This is what passes for version detection on OSX. We set
149 * MACOSX_KQUEUE_IS_BROKEN to true iff we're on a version of OSX before
150 * 10.4.0 (aka 1040). */
152 #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
153 #define MACOSX_KQUEUE_IS_BROKEN \
154 (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1040)
156 #define MACOSX_KQUEUE_IS_BROKEN 0
160 /** Initialize the Libevent library and set up the event base. */
162 tor_libevent_initialize(void)
164 tor_assert(the_event_base
== NULL
);
167 if (MACOSX_KQUEUE_IS_BROKEN
||
168 tor_get_libevent_version(NULL
) < V_OLD(1,1,'b')) {
169 setenv("EVENT_NOKQUEUE","1",1);
173 #ifdef HAVE_EVENT2_EVENT_H
174 the_event_base
= event_base_new();
176 the_event_base
= event_init();
179 #if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
180 /* Making this a NOTICE for now so we can link bugs to a libevent versions
181 * or methods better. */
182 log(LOG_NOTICE
, LD_GENERAL
,
183 "Initialized libevent version %s using method %s. Good.",
184 event_get_version(), tor_libevent_get_method());
186 log(LOG_NOTICE
, LD_GENERAL
,
187 "Initialized old libevent (version 1.0b or earlier).");
188 log(LOG_WARN
, LD_GENERAL
,
189 "You have a *VERY* old version of libevent. It is likely to be buggy; "
190 "please build Tor with a more recent version.");
194 /** Return the current Libevent event base that we're set up to use. */
196 tor_libevent_get_base(void)
198 return the_event_base
;
201 #ifndef HAVE_EVENT_BASE_LOOPEXIT
202 /* Replacement for event_base_loopexit on some very old versions of Libevent
203 that we are not yet brave enough to deprecate. */
205 tor_event_base_loopexit(struct event_base
*base
, struct timeval
*tv
)
207 tor_assert(base
== the_event_base
);
208 return event_loopexit(tv
);
212 /** Return the name of the Libevent backend we're using. */
214 tor_libevent_get_method(void)
216 #ifdef HAVE_EVENT2_EVENT_H
217 return event_base_get_method(the_event_base
);
218 #elif defined(HAVE_EVENT_GET_METHOD)
219 return event_get_method();
225 /** Return the le_version_t for the current version of libevent. If the
226 * version is very new, return LE_OTHER. If the version is so old that it
227 * doesn't support event_get_version(), return LE_OLD. DOCDOC */
229 tor_decode_libevent_version(const char *v
)
231 unsigned major
, minor
, patchlevel
;
235 /* Try the new preferred "1.4.11-stable" format.
236 * Also accept "1.4.14b-stable". */
237 fields
= sscanf(v
, "%u.%u.%u%c%c", &major
, &minor
, &patchlevel
, &c
, &e
);
239 ((fields
== 4 || fields
== 5 ) && (c
== '-' || c
== '_')) ||
240 (fields
== 5 && TOR_ISALPHA(c
) && (e
== '-' || e
== '_'))) {
241 return V(major
,minor
,patchlevel
);
244 /* Try the old "1.3e" format. */
245 fields
= sscanf(v
, "%u.%u%c%c", &major
, &minor
, &c
, &extra
);
246 if (fields
== 3 && TOR_ISALPHA(c
)) {
247 return V_OLD(major
, minor
, c
);
248 } else if (fields
== 2) {
249 return V(major
, minor
, 0);
255 /** Return an integer representing the binary interface of a Libevent library.
256 * Two different versions with different numbers are sure not to be binary
257 * compatible. Two different versions with the same numbers have a decent
258 * chance of binary compatibility.*/
260 le_versions_compatibility(le_version_t v
)
264 if (v
< V_OLD(1,0,'c'))
266 else if (v
< V(1,4,0))
268 else if (v
< V(1,4,99))
270 else if (v
< V(2,0,1))
272 else /* Everything 2.0 and later should be compatible. */
276 /** Return the version number of the currently running version of Libevent.
277 See le_version_t for info on the format.
280 tor_get_libevent_version(const char **v_out
)
284 #if defined(HAVE_EVENT_GET_VERSION_NUMBER)
285 v
= event_get_version();
286 r
= event_get_version_number();
287 #elif defined (HAVE_EVENT_GET_VERSION)
288 v
= event_get_version();
289 r
= tor_decode_libevent_version(v
);
299 /** Return a string representation of the version of the currently running
300 * version of Libevent. */
302 tor_libevent_get_version_str(void)
304 #ifdef HAVE_EVENT_GET_VERSION
305 return event_get_version();
312 * Compare the current Libevent method and version to a list of versions
313 * which are known not to work. Warn the user as appropriate.
316 tor_check_libevent_version(const char *m
, int server
,
317 const char **badness_out
)
319 int buggy
= 0, iffy
= 0, slow
= 0, thread_unsafe
= 0;
320 le_version_t version
;
321 const char *v
= NULL
;
322 const char *badness
= NULL
;
323 const char *sad_os
= "";
325 version
= tor_get_libevent_version(&v
);
327 /* XXX Would it be worthwhile disabling the methods that we know
328 * are buggy, rather than just warning about them and then proceeding
329 * to use them? If so, we should probably not wrap this whole thing
330 * in HAVE_EVENT_GET_VERSION and HAVE_EVENT_GET_METHOD. -RD */
331 /* XXXX The problem is that it's not trivial to get libevent to change it's
332 * method once it's initialized, and it's not trivial to tell what method it
333 * will use without initializing it. I guess we could preemptively disable
334 * buggy libevent modes based on the version _before_ initializing it,
335 * though, but then there's no good way (afaict) to warn "I would have used
336 * kqueue, but instead I'm using select." -NM */
337 /* XXXX022 revist the above; it is fixable now. */
338 if (!strcmp(m
, "kqueue")) {
339 if (version
< V_OLD(1,1,'b'))
341 } else if (!strcmp(m
, "epoll")) {
342 if (version
< V(1,1,0))
344 } else if (!strcmp(m
, "poll")) {
345 if (version
< V_OLD(1,0,'e'))
347 if (version
< V(1,1,0))
349 } else if (!strcmp(m
, "select")) {
350 if (version
< V(1,1,0))
352 } else if (!strcmp(m
, "win32")) {
353 if (version
< V_OLD(1,1,'b'))
357 /* Libevent versions before 1.3b do very badly on operating systems with
358 * user-space threading implementations. */
359 #if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__)
360 if (server
&& version
< V_OLD(1,3,'b')) {
362 sad_os
= "BSD variants";
364 #elif defined(__APPLE__) || defined(__darwin__)
365 if (server
&& version
< V_OLD(1,3,'b')) {
372 log(LOG_WARN
, LD_GENERAL
,
373 "Libevent version %s often crashes when running a Tor server with %s. "
374 "Please use the latest version of libevent (1.3b or later)",v
,sad_os
);
377 log(LOG_WARN
, LD_GENERAL
,
378 "There are serious bugs in using %s with libevent %s. "
379 "Please use the latest version of libevent.", m
, v
);
382 log(LOG_WARN
, LD_GENERAL
,
383 "There are minor bugs in using %s with libevent %s. "
384 "You may want to use the latest version of libevent.", m
, v
);
386 } else if (slow
&& server
) {
387 log(LOG_WARN
, LD_GENERAL
,
388 "libevent %s can be very slow with %s. "
389 "When running a server, please use the latest version of libevent.",
394 *badness_out
= badness
;
397 #if defined(LIBEVENT_VERSION)
398 #define HEADER_VERSION LIBEVENT_VERSION
399 #elif defined(_EVENT_VERSION)
400 #define HEADER_VERSION _EVENT_VERSION
403 /** See whether the headers we were built against differ from the library we
404 * linked against so much that we're likely to crash. If so, warn the
407 tor_check_libevent_header_compatibility(void)
409 (void) le_versions_compatibility
;
410 (void) tor_decode_libevent_version
;
412 /* In libevent versions before 2.0, it's hard to keep binary compatibility
413 * between upgrades, and unpleasant to detect when the version we compiled
414 * against is unlike the version we have linked against. Here's how. */
415 #if defined(HEADER_VERSION) && defined(HAVE_EVENT_GET_VERSION)
416 /* We have a header-file version and a function-call version. Easy. */
417 if (strcmp(HEADER_VERSION
, event_get_version())) {
419 int compat1
= -1, compat2
= -1;
421 v1
= tor_decode_libevent_version(HEADER_VERSION
);
422 v2
= tor_decode_libevent_version(event_get_version());
423 compat1
= le_versions_compatibility(v1
);
424 compat2
= le_versions_compatibility(v2
);
426 verybad
= compat1
!= compat2
;
428 log(verybad
? LOG_WARN
: LOG_NOTICE
,
429 LD_GENERAL
, "We were compiled with headers from version %s "
430 "of Libevent, but we're using a Libevent library that says it's "
431 "version %s.", HEADER_VERSION
, event_get_version());
433 log_warn(LD_GENERAL
, "This will almost certainly make Tor crash.");
435 log_info(LD_GENERAL
, "I think these versions are binary-compatible.");
437 #elif defined(HAVE_EVENT_GET_VERSION)
438 /* event_get_version but no _EVENT_VERSION. We might be in 1.4.0-beta or
439 earlier, where that's normal. To see whether we were compiled with an
440 earlier version, let's see whether the struct event defines MIN_HEAP_IDX.
442 #ifdef HAVE_STRUCT_EVENT_MIN_HEAP_IDX
443 /* The header files are 1.4.0-beta or later. If the version is not
444 * 1.4.0-beta, we are incompatible. */
446 if (strcmp(event_get_version(), "1.4.0-beta")) {
447 log_warn(LD_GENERAL
, "It's a little hard to tell, but you seem to have "
448 "Libevent 1.4.0-beta header files, whereas you have linked "
449 "against Libevent %s. This will probably make Tor crash.",
450 event_get_version());
454 /* Our headers are 1.3e or earlier. If the library version is not 1.4.x or
455 later, we're probably fine. */
457 const char *v
= event_get_version();
458 if ((v
[0] == '1' && v
[2] == '.' && v
[3] > '3') || v
[0] > '1') {
459 log_warn(LD_GENERAL
, "It's a little hard to tell, but you seem to have "
460 "Libevent header file from 1.3e or earlier, whereas you have "
461 "linked against Libevent %s. This will probably make Tor "
462 "crash.", event_get_version());
467 #elif defined(HEADER_VERSION)
468 #warn "_EVENT_VERSION is defined but not get_event_version(): Libevent is odd."
470 /* Your libevent is ancient. */
475 If possible, we're going to try to use Libevent's periodic timer support,
476 since it does a pretty good job of making sure that periodic events get
477 called exactly M seconds apart, rather than starting each one exactly M
478 seconds after the time that the last one was run.
480 #ifdef HAVE_EVENT2_EVENT_H
481 #define HAVE_PERIODIC
482 #define PERIODIC_FLAGS EV_PERSIST
484 #define PERIODIC_FLAGS 0
487 /** Represents a timer that's run every N microseconds by Libevent. */
488 struct periodic_timer_t
{
489 /** Underlying event used to implement this periodic event. */
491 /** The callback we'll be invoking whenever the event triggers */
492 void (*cb
)(struct periodic_timer_t
*, void *);
493 /** User-supplied data for the callback */
495 #ifndef HAVE_PERIODIC
496 /** If Libevent doesn't know how to invoke events every N microseconds,
497 * we'll need to remember the timeout interval here. */
502 /** Libevent callback to implement a periodic event. */
504 periodic_timer_cb(evutil_socket_t fd
, short what
, void *arg
)
506 periodic_timer_t
*timer
= arg
;
509 #ifndef HAVE_PERIODIC
510 /** reschedule the event as needed. */
511 event_add(timer
->ev
, &timer
->tv
);
513 timer
->cb(timer
, timer
->data
);
516 /** Create and schedule a new timer that will run every <b>tv</b> in
517 * the event loop of <b>base</b>. When the timer fires, it will
518 * run the timer in <b>cb</b> with the user-supplied data in <b>data</b>. */
520 periodic_timer_new(struct event_base
*base
,
521 const struct timeval
*tv
,
522 void (*cb
)(periodic_timer_t
*timer
, void *data
),
525 periodic_timer_t
*timer
;
529 timer
= tor_malloc_zero(sizeof(periodic_timer_t
));
530 if (!(timer
->ev
= tor_event_new(base
, -1, PERIODIC_FLAGS
,
531 periodic_timer_cb
, timer
))) {
537 #ifndef HAVE_PERIODIC
538 memcpy(&timer
->tv
, tv
, sizeof(struct timeval
));
540 event_add(timer
->ev
, (struct timeval
*)tv
); /*drop const for old libevent*/
544 /** Stop and free a periodic timer */
546 periodic_timer_free(periodic_timer_t
*timer
)
550 tor_event_free(timer
->ev
);