Tor 0.4.9.0-alpha-dev
compat_libevent.c
Go to the documentation of this file.
1/* Copyright (c) 2009-2021, The Tor Project, Inc. */
2/* See LICENSE for licensing information */
3
4/**
5 * \file compat_libevent.c
6 * \brief Wrappers and utility functions for Libevent.
7 */
8
9#include "orconfig.h"
10#define COMPAT_LIBEVENT_PRIVATE
12
14#include "lib/log/log.h"
15#include "lib/log/util_bug.h"
17
18#include <event2/event.h>
19#include <event2/thread.h>
20#include <string.h>
21
22/** A string which, if it appears in a libevent log, should be ignored. */
23static const char *suppress_msg = NULL;
24/** Callback function passed to event_set_log() so we can intercept
25 * log messages from libevent. */
26STATIC void
27libevent_logging_callback(int severity, const char *msg)
28{
29 char buf[1024];
30 size_t n;
31 if (suppress_msg && strstr(msg, suppress_msg))
32 return;
33 n = strlcpy(buf, msg, sizeof(buf));
34 if (n && n < sizeof(buf) && buf[n-1] == '\n') {
35 buf[n-1] = '\0';
36 }
37 switch (severity) {
38 case _EVENT_LOG_DEBUG:
39 log_debug(LD_NOCB|LD_NET, "Message from libevent: %s", buf);
40 break;
41 case _EVENT_LOG_MSG:
42 log_info(LD_NOCB|LD_NET, "Message from libevent: %s", buf);
43 break;
44 case _EVENT_LOG_WARN:
45 log_warn(LD_NOCB|LD_GENERAL, "Warning from libevent: %s", buf);
46 break;
47 case _EVENT_LOG_ERR:
48 log_err(LD_NOCB|LD_GENERAL, "Error from libevent: %s", buf);
49 break;
50 default:
51 log_warn(LD_NOCB|LD_GENERAL, "Message [%d] from libevent: %s",
52 severity, buf);
53 break;
54 }
55}
56/** Set hook to intercept log messages from libevent. */
57void
59{
60 event_set_log_callback(libevent_logging_callback);
61}
62
63/** Ignore any libevent log message that contains <b>msg</b>. */
64void
66{
67 suppress_msg = msg;
68}
69
70/* Wrapper for event_free() that tolerates tor_event_free(NULL) */
71void
72tor_event_free_(struct event *ev)
73{
74 if (ev == NULL)
75 return;
76 event_free(ev);
77}
78
79/** Global event base for use by the main thread. */
80static struct event_base *the_event_base = NULL;
81
82/**
83 * @defgroup postloop post-loop event helpers
84 *
85 * If we're not careful, Libevent can susceptible to infinite event chains:
86 * one event can activate another, whose callback activates another, whose
87 * callback activates another, ad infinitum. While this is happening,
88 * Libevent won't be checking timeouts, socket-based events, signals, and so
89 * on.
90 *
91 * We solve this problem by marking some events as "post-loop". A post-loop
92 * event behaves like any ordinary event, but any events that _it_ activates
93 * cannot run until Libevent has checked for other events at least once.
94 *
95 * @{ */
96
97/**
98 * An event that stops Libevent from running any more events on the current
99 * iteration of its loop, until it has re-checked for socket events, signal
100 * events, timeouts, etc.
101 */
102static struct event *rescan_mainloop_ev = NULL;
103
104/**
105 * Callback to implement rescan_mainloop_ev: it simply exits the mainloop,
106 * and relies on Tor to re-enter the mainloop since no error has occurred.
107 */
108static void
109rescan_mainloop_cb(evutil_socket_t fd, short events, void *arg)
110{
111 (void)fd;
112 (void)events;
113 struct event_base *the_base = arg;
114 event_base_loopbreak(the_base);
115}
116
117/** @} */
118
119/* This is what passes for version detection on OSX. We set
120 * MACOSX_KQUEUE_IS_BROKEN to true iff we're on a version of OSX before
121 * 10.4.0 (aka 1040). */
122#ifdef __APPLE__
123#ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
124#define MACOSX_KQUEUE_IS_BROKEN \
125 (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1040)
126#else
127#define MACOSX_KQUEUE_IS_BROKEN 0
128#endif /* defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) */
129#endif /* defined(__APPLE__) */
130
131/** Initialize the Libevent library and set up the event base. */
132void
134{
135 tor_assert(the_event_base == NULL);
136 /* some paths below don't use torcfg, so avoid unused variable warnings */
137 (void)torcfg;
138
139 {
140 struct event_config *cfg;
141
142 cfg = event_config_new();
143 tor_assert(cfg);
144
145 /* Telling Libevent not to try to turn locking on can avoid a needless
146 * socketpair() attempt. */
147 event_config_set_flag(cfg, EVENT_BASE_FLAG_NOLOCK);
148
149 if (torcfg->num_cpus > 0)
150 event_config_set_num_cpus_hint(cfg, torcfg->num_cpus);
151
152 /* We can enable changelist support with epoll, since we don't give
153 * Libevent any dup'd fds. This lets us avoid some syscalls. */
154 event_config_set_flag(cfg, EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST);
155
156 the_event_base = event_base_new_with_config(cfg);
157
158 event_config_free(cfg);
159 }
160
161 if (!the_event_base) {
162 /* LCOV_EXCL_START */
163 log_err(LD_GENERAL, "Unable to initialize Libevent: cannot continue.");
164 exit(1); // exit ok: libevent is broken.
165 /* LCOV_EXCL_STOP */
166 }
167
168 rescan_mainloop_ev = event_new(the_event_base, -1, 0,
170 if (!rescan_mainloop_ev) {
171 /* LCOV_EXCL_START */
172 log_err(LD_GENERAL, "Unable to create rescan event: cannot continue.");
173 exit(1); // exit ok: libevent is broken.
174 /* LCOV_EXCL_STOP */
175 }
176
177 log_info(LD_GENERAL,
178 "Initialized libevent version %s using method %s. Good.",
179 event_get_version(), tor_libevent_get_method());
180}
181
182/**
183 * Return true iff the libevent module has been successfully initialized,
184 * and not subsequently shut down.
185 **/
186bool
188{
189 return the_event_base != NULL;
190}
191
192/** Return the current Libevent event base that we're set up to use. */
193MOCK_IMPL(struct event_base *,
195{
196 tor_assert(the_event_base != NULL);
197 return the_event_base;
198}
199
200/** Return the name of the Libevent backend we're using. */
201const char *
203{
204 return event_base_get_method(the_event_base);
205}
206
207/** Return a string representation of the version of the currently running
208 * version of Libevent. */
209const char *
211{
212 return event_get_version();
213}
214
215/** Return a string representation of the version of Libevent that was used
216* at compilation time. */
217const char *
219{
220 return LIBEVENT_VERSION;
221}
222
223/** Represents a timer that's run every N microseconds by Libevent. */
225 /** Underlying event used to implement this periodic event. */
226 struct event *ev;
227 /** The callback we'll be invoking whenever the event triggers */
228 void (*cb)(struct periodic_timer_t *, void *);
229 /** User-supplied data for the callback */
230 void *data;
231};
232
233/** Libevent callback to implement a periodic event. */
234static void
235periodic_timer_cb(evutil_socket_t fd, short what, void *arg)
236{
237 periodic_timer_t *timer = arg;
238 (void) what;
239 (void) fd;
240 timer->cb(timer, timer->data);
241}
242
243/** Create and schedule a new timer that will run every <b>tv</b> in
244 * the event loop of <b>base</b>. When the timer fires, it will
245 * run the timer in <b>cb</b> with the user-supplied data in <b>data</b>. */
247periodic_timer_new(struct event_base *base,
248 const struct timeval *tv,
249 void (*cb)(periodic_timer_t *timer, void *data),
250 void *data)
251{
252 periodic_timer_t *timer;
253 tor_assert(base);
254 tor_assert(tv);
255 tor_assert(cb);
256 timer = tor_malloc_zero(sizeof(periodic_timer_t));
257 if (!(timer->ev = tor_event_new(base, -1, EV_PERSIST,
258 periodic_timer_cb, timer))) {
259 tor_free(timer);
260 return NULL;
261 }
262 timer->cb = cb;
263 timer->data = data;
264 periodic_timer_launch(timer, tv);
265 return timer;
266}
267
268/**
269 * Launch the timer <b>timer</b> to run at <b>tv</b> from now, and every
270 * <b>tv</b> thereafter.
271 *
272 * If the timer is already enabled, this function does nothing.
273 */
274void
276{
277 tor_assert(timer);
278 if (event_pending(timer->ev, EV_TIMEOUT, NULL))
279 return;
280 event_add(timer->ev, tv);
281}
282
283/**
284 * Disable the provided <b>timer</b>, but do not free it.
285 *
286 * You can reenable the same timer later with periodic_timer_launch.
287 *
288 * If the timer is already disabled, this function does nothing.
289 */
290void
292{
293 tor_assert(timer);
294 (void) event_del(timer->ev);
295}
296
297/** Stop and free a periodic timer */
298void
300{
301 if (!timer)
302 return;
303 tor_event_free(timer->ev);
304 tor_free(timer);
305}
306
307/**
308 * Type used to represent events that run directly from the main loop,
309 * either because they are activated from elsewhere in the code, or
310 * because they have a simple timeout.
311 *
312 * We use this type to avoid exposing Libevent's API throughout the rest
313 * of the codebase.
314 *
315 * This type can't be used for all events: it doesn't handle events that
316 * are triggered by signals or by sockets.
317 */
319 struct event *ev;
320 void (*cb)(mainloop_event_t *, void *);
321 void *userdata;
322};
323
324/**
325 * Internal: Implements mainloop event using a libevent event.
326 */
327static void
328mainloop_event_cb(evutil_socket_t fd, short what, void *arg)
329{
330 (void)fd;
331 (void)what;
332 mainloop_event_t *mev = arg;
333 mev->cb(mev, mev->userdata);
334}
335
336/**
337 * As mainloop_event_cb, but implements a post-loop event.
338 */
339static void
340mainloop_event_postloop_cb(evutil_socket_t fd, short what, void *arg)
341{
342 (void)fd;
343 (void)what;
344
345 /* Note that if rescan_mainloop_ev is already activated,
346 * event_active() will do nothing: only the first post-loop event that
347 * happens each time through the event loop will cause it to be
348 * activated.
349 *
350 * Because event_active() puts events on a FIFO queue, every event
351 * that is made active _after_ rescan_mainloop_ev will get its
352 * callback run after rescan_mainloop_cb is called -- that is, on the
353 * next iteration of the loop.
354 */
355 event_active(rescan_mainloop_ev, EV_READ, 1);
356
357 mainloop_event_t *mev = arg;
358 mev->cb(mev, mev->userdata);
359}
360
361/**
362 * Helper for mainloop_event_new() and mainloop_event_postloop_new().
363 */
364static mainloop_event_t *
366 void (*cb)(mainloop_event_t *, void *),
367 void *userdata)
368{
369 tor_assert(cb);
370
371 struct event_base *base = tor_libevent_get_base();
372 mainloop_event_t *mev = tor_malloc_zero(sizeof(mainloop_event_t));
373 mev->ev = tor_event_new(base, -1, 0,
375 mev);
376 tor_assert(mev->ev);
377 mev->cb = cb;
378 mev->userdata = userdata;
379 return mev;
380}
381
382/**
383 * Create and return a new mainloop_event_t to run the function <b>cb</b>.
384 *
385 * When run, the callback function will be passed the mainloop_event_t
386 * and <b>userdata</b> as its arguments. The <b>userdata</b> pointer
387 * must remain valid for as long as the mainloop_event_t event exists:
388 * it is your responsibility to free it.
389 *
390 * The event is not scheduled by default: Use mainloop_event_activate()
391 * or mainloop_event_schedule() to make it run.
392 */
395 void *userdata)
396{
397 return mainloop_event_new_impl(0, cb, userdata);
398}
399
400/**
401 * As mainloop_event_new(), but create a post-loop event.
402 *
403 * A post-loop event behaves like any ordinary event, but any events
404 * that _it_ activates cannot run until Libevent has checked for other
405 * events at least once.
406 */
409 void *userdata)
410{
411 return mainloop_event_new_impl(1, cb, userdata);
412}
413
414/**
415 * Schedule <b>event</b> to run in the main loop, immediately. If it is
416 * not scheduled, it will run anyway. If it is already scheduled to run
417 * later, it will run now instead. This function will have no effect if
418 * the event is already scheduled to run.
419 *
420 * This function may only be called from the main thread.
421 */
422void
424{
425 tor_assert(event);
426 event_active(event->ev, EV_READ, 1);
427}
428
429/** Schedule <b>event</b> to run in the main loop, after a delay of <b>tv</b>.
430 *
431 * If the event is scheduled for a different time, cancel it and run
432 * after this delay instead. If the event is currently pending to run
433 * <b>now</b>, has no effect.
434 *
435 * Do not call this function with <b>tv</b> == NULL -- use
436 * mainloop_event_activate() instead.
437 *
438 * This function may only be called from the main thread.
439 */
440int
442{
443 tor_assert(event);
444 if (BUG(tv == NULL)) {
445 // LCOV_EXCL_START
447 return 0;
448 // LCOV_EXCL_STOP
449 }
450 return event_add(event->ev, tv);
451}
452
453/** Cancel <b>event</b> if it is currently active or pending. (Do nothing if
454 * the event is not currently active or pending.) */
455void
457{
458 if (!event)
459 return;
460 (void) event_del(event->ev);
461}
462
463/** Cancel <b>event</b> and release all storage associated with it. */
464void
466{
467 if (!event)
468 return;
469 tor_event_free(event->ev);
470 memset(event, 0xb8, sizeof(*event));
471 tor_free(event);
472}
473
474int
475tor_init_libevent_rng(void)
476{
477 int rv = 0;
478 char buf[256];
479 if (evutil_secure_rng_init() < 0) {
480 rv = -1;
481 }
482 crypto_rand(buf, 32);
483#ifdef HAVE_EVUTIL_SECURE_RNG_ADD_BYTES
484 evutil_secure_rng_add_bytes(buf, 32);
485#endif
486 evutil_secure_rng_get_bytes(buf, sizeof(buf));
487 return rv;
488}
489
490/**
491 * Un-initialize libevent in preparation for an exit
492 */
493void
495{
496 tor_event_free(rescan_mainloop_ev);
497 if (the_event_base)
498 event_base_free(the_event_base);
499 the_event_base = NULL;
500}
501
502/**
503 * Run the event loop for the provided event_base, handling events until
504 * something stops it. If <b>once</b> is set, then just poll-and-run
505 * once, then exit. Return 0 on success, -1 if an error occurred, or 1
506 * if we exited because no events were pending or active.
507 *
508 * This isn't reentrant or multithreaded.
509 */
510int
511tor_libevent_run_event_loop(struct event_base *base, int once)
512{
513 const int flags = once ? EVLOOP_ONCE : 0;
514 return event_base_loop(base, flags);
515}
516
517/** Tell the event loop to exit after <b>delay</b>. If <b>delay</b> is NULL,
518 * instead exit after we're done running the currently active events. */
519void
521 const struct timeval *delay)
522{
523 event_base_loopexit(base, delay);
524}
525
526/** Tell the event loop to exit after running whichever callback is currently
527 * active. */
528void
530{
531 event_base_loopbreak(base);
532}
533
534#if defined(TOR_UNIT_TESTS)
535/** For testing: called post-fork to make libevent reinitialize
536 * kernel structures. */
537void
538tor_libevent_postfork(void)
539{
540 int r = event_reinit(tor_libevent_get_base());
541 tor_assert(r == 0);
542}
543#endif /* defined(TOR_UNIT_TESTS) */
STATIC void libevent_logging_callback(int severity, const char *msg)
const char * tor_libevent_get_header_version_str(void)
void suppress_libevent_log_msg(const char *msg)
bool tor_libevent_is_initialized(void)
void mainloop_event_cancel(mainloop_event_t *event)
void periodic_timer_launch(periodic_timer_t *timer, const struct timeval *tv)
static struct event_base * the_event_base
void tor_libevent_exit_loop_after_callback(struct event_base *base)
void tor_libevent_initialize(tor_libevent_cfg_t *torcfg)
void mainloop_event_free_(mainloop_event_t *event)
int tor_libevent_run_event_loop(struct event_base *base, int once)
const char * tor_libevent_get_version_str(void)
static void mainloop_event_cb(evutil_socket_t fd, short what, void *arg)
void tor_libevent_exit_loop_after_delay(struct event_base *base, const struct timeval *delay)
mainloop_event_t * mainloop_event_postloop_new(void(*cb)(mainloop_event_t *, void *), void *userdata)
static void periodic_timer_cb(evutil_socket_t fd, short what, void *arg)
int mainloop_event_schedule(mainloop_event_t *event, const struct timeval *tv)
void tor_libevent_free_all(void)
periodic_timer_t * periodic_timer_new(struct event_base *base, const struct timeval *tv, void(*cb)(periodic_timer_t *timer, void *data), void *data)
void periodic_timer_free_(periodic_timer_t *timer)
static const char * suppress_msg
const char * tor_libevent_get_method(void)
struct event_base * tor_libevent_get_base(void)
void configure_libevent_logging(void)
static mainloop_event_t * mainloop_event_new_impl(int postloop, void(*cb)(mainloop_event_t *, void *), void *userdata)
void periodic_timer_disable(periodic_timer_t *timer)
mainloop_event_t * mainloop_event_new(void(*cb)(mainloop_event_t *, void *), void *userdata)
void mainloop_event_activate(mainloop_event_t *event)
static void mainloop_event_postloop_cb(evutil_socket_t fd, short what, void *arg)
Header for compat_libevent.c.
Header for compat_string.c.
void crypto_rand(char *to, size_t n)
Definition: crypto_rand.c:479
Common functions for using (pseudo-)random number generators.
static void rescan_mainloop_cb(evutil_socket_t fd, short events, void *arg)
static struct event * rescan_mainloop_ev
Headers for log.c.
#define LD_NOCB
Definition: log.h:144
#define LD_NET
Definition: log.h:66
#define LD_GENERAL
Definition: log.h:62
#define tor_free(p)
Definition: malloc.h:56
struct event * ev
void(* cb)(struct periodic_timer_t *, void *)
#define STATIC
Definition: testsupport.h:32
#define MOCK_IMPL(rv, funcname, arglist)
Definition: testsupport.h:133
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition: util_bug.h:103