Tor  0.4.7.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. */
23 static const char *suppress_msg = NULL;
24 /** Callback function passed to event_set_log() so we can intercept
25  * log messages from libevent. */
26 STATIC void
27 libevent_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. */
57 void
59 {
60  event_set_log_callback(libevent_logging_callback);
61 }
62 
63 /** Ignore any libevent log message that contains <b>msg</b>. */
64 void
65 suppress_libevent_log_msg(const char *msg)
66 {
67  suppress_msg = msg;
68 }
69 
70 /* Wrapper for event_free() that tolerates tor_event_free(NULL) */
71 void
72 tor_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. */
80 static 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  */
102 static 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  */
108 static void
109 rescan_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. */
132 void
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  int attempts = 0;
141  struct event_config *cfg;
142 
143  ++attempts;
144  cfg = event_config_new();
145  tor_assert(cfg);
146 
147  /* Telling Libevent not to try to turn locking on can avoid a needless
148  * socketpair() attempt. */
149  event_config_set_flag(cfg, EVENT_BASE_FLAG_NOLOCK);
150 
151  if (torcfg->num_cpus > 0)
152  event_config_set_num_cpus_hint(cfg, torcfg->num_cpus);
153 
154  /* We can enable changelist support with epoll, since we don't give
155  * Libevent any dup'd fds. This lets us avoid some syscalls. */
156  event_config_set_flag(cfg, EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST);
157 
158  the_event_base = event_base_new_with_config(cfg);
159 
160  event_config_free(cfg);
161  }
162 
163  if (!the_event_base) {
164  /* LCOV_EXCL_START */
165  log_err(LD_GENERAL, "Unable to initialize Libevent: cannot continue.");
166  exit(1); // exit ok: libevent is broken.
167  /* LCOV_EXCL_STOP */
168  }
169 
170  rescan_mainloop_ev = event_new(the_event_base, -1, 0,
172  if (!rescan_mainloop_ev) {
173  /* LCOV_EXCL_START */
174  log_err(LD_GENERAL, "Unable to create rescan event: cannot continue.");
175  exit(1); // exit ok: libevent is broken.
176  /* LCOV_EXCL_STOP */
177  }
178 
179  log_info(LD_GENERAL,
180  "Initialized libevent version %s using method %s. Good.",
181  event_get_version(), tor_libevent_get_method());
182 }
183 
184 /**
185  * Return true iff the libevent module has been successfully initialized,
186  * and not subsequently shut down.
187  **/
188 bool
190 {
191  return the_event_base != NULL;
192 }
193 
194 /** Return the current Libevent event base that we're set up to use. */
195 MOCK_IMPL(struct event_base *,
197 {
198  tor_assert(the_event_base != NULL);
199  return the_event_base;
200 }
201 
202 /** Return the name of the Libevent backend we're using. */
203 const char *
205 {
206  return event_base_get_method(the_event_base);
207 }
208 
209 /** Return a string representation of the version of the currently running
210  * version of Libevent. */
211 const char *
213 {
214  return event_get_version();
215 }
216 
217 /** Return a string representation of the version of Libevent that was used
218 * at compilation time. */
219 const char *
221 {
222  return LIBEVENT_VERSION;
223 }
224 
225 /** Represents a timer that's run every N microseconds by Libevent. */
227  /** Underlying event used to implement this periodic event. */
228  struct event *ev;
229  /** The callback we'll be invoking whenever the event triggers */
230  void (*cb)(struct periodic_timer_t *, void *);
231  /** User-supplied data for the callback */
232  void *data;
233 };
234 
235 /** Libevent callback to implement a periodic event. */
236 static void
237 periodic_timer_cb(evutil_socket_t fd, short what, void *arg)
238 {
239  periodic_timer_t *timer = arg;
240  (void) what;
241  (void) fd;
242  timer->cb(timer, timer->data);
243 }
244 
245 /** Create and schedule a new timer that will run every <b>tv</b> in
246  * the event loop of <b>base</b>. When the timer fires, it will
247  * run the timer in <b>cb</b> with the user-supplied data in <b>data</b>. */
249 periodic_timer_new(struct event_base *base,
250  const struct timeval *tv,
251  void (*cb)(periodic_timer_t *timer, void *data),
252  void *data)
253 {
254  periodic_timer_t *timer;
255  tor_assert(base);
256  tor_assert(tv);
257  tor_assert(cb);
258  timer = tor_malloc_zero(sizeof(periodic_timer_t));
259  if (!(timer->ev = tor_event_new(base, -1, EV_PERSIST,
260  periodic_timer_cb, timer))) {
261  tor_free(timer);
262  return NULL;
263  }
264  timer->cb = cb;
265  timer->data = data;
266  periodic_timer_launch(timer, tv);
267  return timer;
268 }
269 
270 /**
271  * Launch the timer <b>timer</b> to run at <b>tv</b> from now, and every
272  * <b>tv</b> thereafter.
273  *
274  * If the timer is already enabled, this function does nothing.
275  */
276 void
278 {
279  tor_assert(timer);
280  if (event_pending(timer->ev, EV_TIMEOUT, NULL))
281  return;
282  event_add(timer->ev, tv);
283 }
284 
285 /**
286  * Disable the provided <b>timer</b>, but do not free it.
287  *
288  * You can reenable the same timer later with periodic_timer_launch.
289  *
290  * If the timer is already disabled, this function does nothing.
291  */
292 void
294 {
295  tor_assert(timer);
296  (void) event_del(timer->ev);
297 }
298 
299 /** Stop and free a periodic timer */
300 void
302 {
303  if (!timer)
304  return;
305  tor_event_free(timer->ev);
306  tor_free(timer);
307 }
308 
309 /**
310  * Type used to represent events that run directly from the main loop,
311  * either because they are activated from elsewhere in the code, or
312  * because they have a simple timeout.
313  *
314  * We use this type to avoid exposing Libevent's API throughout the rest
315  * of the codebase.
316  *
317  * This type can't be used for all events: it doesn't handle events that
318  * are triggered by signals or by sockets.
319  */
321  struct event *ev;
322  void (*cb)(mainloop_event_t *, void *);
323  void *userdata;
324 };
325 
326 /**
327  * Internal: Implements mainloop event using a libevent event.
328  */
329 static void
330 mainloop_event_cb(evutil_socket_t fd, short what, void *arg)
331 {
332  (void)fd;
333  (void)what;
334  mainloop_event_t *mev = arg;
335  mev->cb(mev, mev->userdata);
336 }
337 
338 /**
339  * As mainloop_event_cb, but implements a post-loop event.
340  */
341 static void
342 mainloop_event_postloop_cb(evutil_socket_t fd, short what, void *arg)
343 {
344  (void)fd;
345  (void)what;
346 
347  /* Note that if rescan_mainloop_ev is already activated,
348  * event_active() will do nothing: only the first post-loop event that
349  * happens each time through the event loop will cause it to be
350  * activated.
351  *
352  * Because event_active() puts events on a FIFO queue, every event
353  * that is made active _after_ rescan_mainloop_ev will get its
354  * callback run after rescan_mainloop_cb is called -- that is, on the
355  * next iteration of the loop.
356  */
357  event_active(rescan_mainloop_ev, EV_READ, 1);
358 
359  mainloop_event_t *mev = arg;
360  mev->cb(mev, mev->userdata);
361 }
362 
363 /**
364  * Helper for mainloop_event_new() and mainloop_event_postloop_new().
365  */
366 static mainloop_event_t *
368  void (*cb)(mainloop_event_t *, void *),
369  void *userdata)
370 {
371  tor_assert(cb);
372 
373  struct event_base *base = tor_libevent_get_base();
374  mainloop_event_t *mev = tor_malloc_zero(sizeof(mainloop_event_t));
375  mev->ev = tor_event_new(base, -1, 0,
377  mev);
378  tor_assert(mev->ev);
379  mev->cb = cb;
380  mev->userdata = userdata;
381  return mev;
382 }
383 
384 /**
385  * Create and return a new mainloop_event_t to run the function <b>cb</b>.
386  *
387  * When run, the callback function will be passed the mainloop_event_t
388  * and <b>userdata</b> as its arguments. The <b>userdata</b> pointer
389  * must remain valid for as long as the mainloop_event_t event exists:
390  * it is your responsibility to free it.
391  *
392  * The event is not scheduled by default: Use mainloop_event_activate()
393  * or mainloop_event_schedule() to make it run.
394  */
396 mainloop_event_new(void (*cb)(mainloop_event_t *, void *),
397  void *userdata)
398 {
399  return mainloop_event_new_impl(0, cb, userdata);
400 }
401 
402 /**
403  * As mainloop_event_new(), but create a post-loop event.
404  *
405  * A post-loop event behaves like any ordinary event, but any events
406  * that _it_ activates cannot run until Libevent has checked for other
407  * events at least once.
408  */
411  void *userdata)
412 {
413  return mainloop_event_new_impl(1, cb, userdata);
414 }
415 
416 /**
417  * Schedule <b>event</b> to run in the main loop, immediately. If it is
418  * not scheduled, it will run anyway. If it is already scheduled to run
419  * later, it will run now instead. This function will have no effect if
420  * the event is already scheduled to run.
421  *
422  * This function may only be called from the main thread.
423  */
424 void
426 {
427  tor_assert(event);
428  event_active(event->ev, EV_READ, 1);
429 }
430 
431 /** Schedule <b>event</b> to run in the main loop, after a delay of <b>tv</b>.
432  *
433  * If the event is scheduled for a different time, cancel it and run
434  * after this delay instead. If the event is currently pending to run
435  * <b>now</b>, has no effect.
436  *
437  * Do not call this function with <b>tv</b> == NULL -- use
438  * mainloop_event_activate() instead.
439  *
440  * This function may only be called from the main thread.
441  */
442 int
444 {
445  tor_assert(event);
446  if (BUG(tv == NULL)) {
447  // LCOV_EXCL_START
449  return 0;
450  // LCOV_EXCL_STOP
451  }
452  return event_add(event->ev, tv);
453 }
454 
455 /** Cancel <b>event</b> if it is currently active or pending. (Do nothing if
456  * the event is not currently active or pending.) */
457 void
459 {
460  if (!event)
461  return;
462  (void) event_del(event->ev);
463 }
464 
465 /** Cancel <b>event</b> and release all storage associated with it. */
466 void
468 {
469  if (!event)
470  return;
471  tor_event_free(event->ev);
472  memset(event, 0xb8, sizeof(*event));
473  tor_free(event);
474 }
475 
476 int
477 tor_init_libevent_rng(void)
478 {
479  int rv = 0;
480  char buf[256];
481  if (evutil_secure_rng_init() < 0) {
482  rv = -1;
483  }
484  crypto_rand(buf, 32);
485 #ifdef HAVE_EVUTIL_SECURE_RNG_ADD_BYTES
486  evutil_secure_rng_add_bytes(buf, 32);
487 #endif
488  evutil_secure_rng_get_bytes(buf, sizeof(buf));
489  return rv;
490 }
491 
492 /**
493  * Un-initialize libevent in preparation for an exit
494  */
495 void
497 {
498  tor_event_free(rescan_mainloop_ev);
499  if (the_event_base)
500  event_base_free(the_event_base);
501  the_event_base = NULL;
502 }
503 
504 /**
505  * Run the event loop for the provided event_base, handling events until
506  * something stops it. If <b>once</b> is set, then just poll-and-run
507  * once, then exit. Return 0 on success, -1 if an error occurred, or 1
508  * if we exited because no events were pending or active.
509  *
510  * This isn't reentrant or multithreaded.
511  */
512 int
513 tor_libevent_run_event_loop(struct event_base *base, int once)
514 {
515  const int flags = once ? EVLOOP_ONCE : 0;
516  return event_base_loop(base, flags);
517 }
518 
519 /** Tell the event loop to exit after <b>delay</b>. If <b>delay</b> is NULL,
520  * instead exit after we're done running the currently active events. */
521 void
522 tor_libevent_exit_loop_after_delay(struct event_base *base,
523  const struct timeval *delay)
524 {
525  event_base_loopexit(base, delay);
526 }
527 
528 /** Tell the event loop to exit after running whichever callback is currently
529  * active. */
530 void
532 {
533  event_base_loopbreak(base);
534 }
535 
536 #if defined(TOR_UNIT_TESTS)
537 /** For testing: called post-fork to make libevent reinitialize
538  * kernel structures. */
539 void
540 tor_libevent_postfork(void)
541 {
542  int r = event_reinit(tor_libevent_get_base());
543  tor_assert(r == 0);
544 }
545 #endif /* defined(TOR_UNIT_TESTS) */
STATIC void libevent_logging_callback(int severity, const char *msg)
void suppress_libevent_log_msg(const char *msg)
bool tor_libevent_is_initialized(void)
struct event_base * tor_libevent_get_base(void)
static mainloop_event_t * mainloop_event_new_impl(int postloop, void(*cb)(mainloop_event_t *, void *), void *userdata)
const char * tor_libevent_get_version_str(void)
mainloop_event_t * mainloop_event_postloop_new(void(*cb)(mainloop_event_t *, void *), void *userdata)
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
const char * tor_libevent_get_method(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 tor_libevent_exit_loop_after_callback(struct event_base *base)
mainloop_event_t * mainloop_event_new(void(*cb)(mainloop_event_t *, void *), void *userdata)
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_header_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)
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)
void periodic_timer_free_(periodic_timer_t *timer)
static const char * suppress_msg
void configure_libevent_logging(void)
void periodic_timer_disable(periodic_timer_t *timer)
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:477
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:52
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:102