LCOV - code coverage report
Current view: top level - lib/evloop - compat_libevent.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 162 169 95.9 %
Date: 2021-11-24 03:28:48 Functions: 30 31 96.8 %

          Line data    Source code
       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
      11             : #include "lib/evloop/compat_libevent.h"
      12             : 
      13             : #include "lib/crypt_ops/crypto_rand.h"
      14             : #include "lib/log/log.h"
      15             : #include "lib/log/util_bug.h"
      16             : #include "lib/string/compat_string.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           9 : libevent_logging_callback(int severity, const char *msg)
      28             : {
      29           9 :   char buf[1024];
      30           9 :   size_t n;
      31           9 :   if (suppress_msg && strstr(msg, suppress_msg))
      32           1 :     return;
      33           8 :   n = strlcpy(buf, msg, sizeof(buf));
      34           8 :   if (n && n < sizeof(buf) && buf[n-1] == '\n') {
      35           1 :     buf[n-1] = '\0';
      36             :   }
      37           8 :   switch (severity) {
      38             :     case _EVENT_LOG_DEBUG:
      39           2 :       log_debug(LD_NOCB|LD_NET, "Message from libevent: %s", buf);
      40           2 :       break;
      41           2 :     case _EVENT_LOG_MSG:
      42           2 :       log_info(LD_NOCB|LD_NET, "Message from libevent: %s", buf);
      43           2 :       break;
      44           1 :     case _EVENT_LOG_WARN:
      45           1 :       log_warn(LD_NOCB|LD_GENERAL, "Warning from libevent: %s", buf);
      46           1 :       break;
      47           1 :     case _EVENT_LOG_ERR:
      48           1 :       log_err(LD_NOCB|LD_GENERAL, "Error from libevent: %s", buf);
      49           1 :       break;
      50           2 :     default:
      51           2 :       log_warn(LD_NOCB|LD_GENERAL, "Message [%d] from libevent: %s",
      52             :           severity, buf);
      53           2 :       break;
      54             :   }
      55             : }
      56             : /** Set hook to intercept log messages from libevent. */
      57             : void
      58           5 : configure_libevent_logging(void)
      59             : {
      60           5 :   event_set_log_callback(libevent_logging_callback);
      61           5 : }
      62             : 
      63             : /** Ignore any libevent log message that contains <b>msg</b>. */
      64             : void
      65          10 : suppress_libevent_log_msg(const char *msg)
      66             : {
      67          10 :   suppress_msg = msg;
      68          10 : }
      69             : 
      70             : /* Wrapper for event_free() that tolerates tor_event_free(NULL) */
      71             : void
      72        1427 : tor_event_free_(struct event *ev)
      73             : {
      74        1427 :   if (ev == NULL)
      75             :     return;
      76         104 :   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      104570 : rescan_mainloop_cb(evutil_socket_t fd, short events, void *arg)
     110             : {
     111      104570 :   (void)fd;
     112      104570 :   (void)events;
     113      104570 :   struct event_base *the_base = arg;
     114      104570 :   event_base_loopbreak(the_base);
     115      104570 : }
     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
     133          21 : tor_libevent_initialize(tor_libevent_cfg_t *torcfg)
     134             : {
     135          21 :   tor_assert(the_event_base == NULL);
     136             :   /* some paths below don't use torcfg, so avoid unused variable warnings */
     137          21 :   (void)torcfg;
     138             : 
     139             :   {
     140          21 :     int attempts = 0;
     141          21 :     struct event_config *cfg;
     142             : 
     143          21 :     ++attempts;
     144          21 :     cfg = event_config_new();
     145          21 :     tor_assert(cfg);
     146             : 
     147             :     /* Telling Libevent not to try to turn locking on can avoid a needless
     148             :      * socketpair() attempt. */
     149          21 :     event_config_set_flag(cfg, EVENT_BASE_FLAG_NOLOCK);
     150             : 
     151          21 :     if (torcfg->num_cpus > 0)
     152           4 :       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          21 :     event_config_set_flag(cfg, EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST);
     157             : 
     158          21 :     the_event_base = event_base_new_with_config(cfg);
     159             : 
     160          21 :     event_config_free(cfg);
     161             :   }
     162             : 
     163          21 :   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          21 :   rescan_mainloop_ev = event_new(the_event_base, -1, 0,
     171             :                                  rescan_mainloop_cb, the_event_base);
     172          21 :   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          21 :   log_info(LD_GENERAL,
     180             :       "Initialized libevent version %s using method %s. Good.",
     181             :       event_get_version(), tor_libevent_get_method());
     182          21 : }
     183             : 
     184             : /**
     185             :  * Return true iff the libevent module has been successfully initialized,
     186             :  * and not subsequently shut down.
     187             :  **/
     188             : bool
     189           4 : tor_libevent_is_initialized(void)
     190             : {
     191           4 :   return the_event_base != NULL;
     192             : }
     193             : 
     194             : /** Return the current Libevent event base that we're set up to use. */
     195      106969 : MOCK_IMPL(struct event_base *,
     196             : tor_libevent_get_base, (void))
     197             : {
     198      106969 :   tor_assert(the_event_base != NULL);
     199      106969 :   return the_event_base;
     200             : }
     201             : 
     202             : /** Return the name of the Libevent backend we're using. */
     203             : const char *
     204          21 : tor_libevent_get_method(void)
     205             : {
     206          21 :   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 *
     212         235 : tor_libevent_get_version_str(void)
     213             : {
     214         235 :   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 *
     220           1 : tor_libevent_get_header_version_str(void)
     221             : {
     222           1 :   return LIBEVENT_VERSION;
     223             : }
     224             : 
     225             : /** Represents a timer that's run every N microseconds by Libevent. */
     226             : struct periodic_timer_t {
     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          13 : periodic_timer_cb(evutil_socket_t fd, short what, void *arg)
     238             : {
     239          13 :   periodic_timer_t *timer = arg;
     240          13 :   (void) what;
     241          13 :   (void) fd;
     242          13 :   timer->cb(timer, timer->data);
     243          13 : }
     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>. */
     248             : periodic_timer_t *
     249           7 : 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           7 :   periodic_timer_t *timer;
     255           7 :   tor_assert(base);
     256           7 :   tor_assert(tv);
     257           7 :   tor_assert(cb);
     258           7 :   timer = tor_malloc_zero(sizeof(periodic_timer_t));
     259           7 :   if (!(timer->ev = tor_event_new(base, -1, EV_PERSIST,
     260             :                                   periodic_timer_cb, timer))) {
     261           0 :     tor_free(timer);
     262           0 :     return NULL;
     263             :   }
     264           7 :   timer->cb = cb;
     265           7 :   timer->data = data;
     266           7 :   periodic_timer_launch(timer, tv);
     267           7 :   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
     277           7 : periodic_timer_launch(periodic_timer_t *timer, const struct timeval *tv)
     278             : {
     279           7 :   tor_assert(timer);
     280           7 :   if (event_pending(timer->ev, EV_TIMEOUT, NULL))
     281             :     return;
     282           7 :   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
     293           0 : periodic_timer_disable(periodic_timer_t *timer)
     294             : {
     295           0 :   tor_assert(timer);
     296           0 :   (void) event_del(timer->ev);
     297           0 : }
     298             : 
     299             : /** Stop and free a periodic timer */
     300             : void
     301         242 : periodic_timer_free_(periodic_timer_t *timer)
     302             : {
     303         242 :   if (!timer)
     304             :     return;
     305           7 :   tor_event_free(timer->ev);
     306           7 :   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             :  */
     320             : struct mainloop_event_t {
     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        1764 : mainloop_event_cb(evutil_socket_t fd, short what, void *arg)
     331             : {
     332        1764 :   (void)fd;
     333        1764 :   (void)what;
     334        1764 :   mainloop_event_t *mev = arg;
     335        1764 :   mev->cb(mev, mev->userdata);
     336        1764 : }
     337             : 
     338             : /**
     339             :  * As mainloop_event_cb, but implements a post-loop event.
     340             :  */
     341             : static void
     342      104570 : mainloop_event_postloop_cb(evutil_socket_t fd, short what, void *arg)
     343             : {
     344      104570 :   (void)fd;
     345      104570 :   (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      104570 :   event_active(rescan_mainloop_ev, EV_READ, 1);
     358             : 
     359      104570 :   mainloop_event_t *mev = arg;
     360      104570 :   mev->cb(mev, mev->userdata);
     361      104570 : }
     362             : 
     363             : /**
     364             :  * Helper for mainloop_event_new() and mainloop_event_postloop_new().
     365             :  */
     366             : static mainloop_event_t *
     367         215 : mainloop_event_new_impl(int postloop,
     368             :                         void (*cb)(mainloop_event_t *, void *),
     369             :                         void *userdata)
     370             : {
     371         215 :   tor_assert(cb);
     372             : 
     373         215 :   struct event_base *base = tor_libevent_get_base();
     374         215 :   mainloop_event_t *mev = tor_malloc_zero(sizeof(mainloop_event_t));
     375         387 :   mev->ev = tor_event_new(base, -1, 0,
     376             :                   postloop ? mainloop_event_postloop_cb : mainloop_event_cb,
     377             :                   mev);
     378         215 :   tor_assert(mev->ev);
     379         215 :   mev->cb = cb;
     380         215 :   mev->userdata = userdata;
     381         215 :   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             :  */
     395             : mainloop_event_t *
     396         172 : mainloop_event_new(void (*cb)(mainloop_event_t *, void *),
     397             :                    void *userdata)
     398             : {
     399         172 :   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             :  */
     409             : mainloop_event_t *
     410          43 : mainloop_event_postloop_new(void (*cb)(mainloop_event_t *, void *),
     411             :                             void *userdata)
     412             : {
     413          43 :   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
     425      104789 : mainloop_event_activate(mainloop_event_t *event)
     426             : {
     427      104789 :   tor_assert(event);
     428      104789 :   event_active(event->ev, EV_READ, 1);
     429      104789 : }
     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
     443        1840 : mainloop_event_schedule(mainloop_event_t *event, const struct timeval *tv)
     444             : {
     445        1840 :   tor_assert(event);
     446        1840 :   if (BUG(tv == NULL)) {
     447             :     // LCOV_EXCL_START
     448             :     mainloop_event_activate(event);
     449             :     return 0;
     450             :     // LCOV_EXCL_STOP
     451             :   }
     452        1840 :   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
     458          40 : mainloop_event_cancel(mainloop_event_t *event)
     459             : {
     460          40 :   if (!event)
     461             :     return;
     462          40 :   (void) event_del(event->ev);
     463             : }
     464             : 
     465             : /** Cancel <b>event</b> and release all storage associated with it. */
     466             : void
     467       10684 : mainloop_event_free_(mainloop_event_t *event)
     468             : {
     469       10684 :   if (!event)
     470             :     return;
     471          78 :   tor_event_free(event->ev);
     472          78 :   memset(event, 0xb8, sizeof(*event));
     473          78 :   tor_free(event);
     474             : }
     475             : 
     476             : int
     477        5553 : tor_init_libevent_rng(void)
     478             : {
     479        5553 :   int rv = 0;
     480        5553 :   char buf[256];
     481        5553 :   if (evutil_secure_rng_init() < 0) {
     482           0 :     rv = -1;
     483             :   }
     484        5553 :   crypto_rand(buf, 32);
     485             : #ifdef HAVE_EVUTIL_SECURE_RNG_ADD_BYTES
     486        5553 :   evutil_secure_rng_add_bytes(buf, 32);
     487             : #endif
     488        5553 :   evutil_secure_rng_get_bytes(buf, sizeof(buf));
     489        5553 :   return rv;
     490             : }
     491             : 
     492             : /**
     493             :  * Un-initialize libevent in preparation for an exit
     494             :  */
     495             : void
     496         235 : tor_libevent_free_all(void)
     497             : {
     498         235 :   tor_event_free(rescan_mainloop_ev);
     499         235 :   if (the_event_base)
     500           4 :     event_base_free(the_event_base);
     501         235 :   the_event_base = NULL;
     502         235 : }
     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      104581 : tor_libevent_run_event_loop(struct event_base *base, int once)
     514             : {
     515      104581 :   const int flags = once ? EVLOOP_ONCE : 0;
     516      104581 :   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          14 : tor_libevent_exit_loop_after_delay(struct event_base *base,
     523             :                                    const struct timeval *delay)
     524             : {
     525          14 :   event_base_loopexit(base, delay);
     526          14 : }
     527             : 
     528             : /** Tell the event loop to exit after running whichever callback is currently
     529             :  * active. */
     530             : void
     531         223 : tor_libevent_exit_loop_after_callback(struct event_base *base)
     532             : {
     533         223 :   event_base_loopbreak(base);
     534         223 : }
     535             : 
     536             : #if defined(TOR_UNIT_TESTS)
     537             : /** For testing: called post-fork to make libevent reinitialize
     538             :  * kernel structures. */
     539             : void
     540        1854 : tor_libevent_postfork(void)
     541             : {
     542        1854 :   int r = event_reinit(tor_libevent_get_base());
     543        1854 :   tor_assert(r == 0);
     544        1854 : }
     545             : #endif /* defined(TOR_UNIT_TESTS) */

Generated by: LCOV version 1.14