compat_libevent.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. /* Copyright (c) 2009-2011, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /**
  4. * \file compat_libevent.c
  5. * \brief Wrappers to handle porting between different versions of libevent.
  6. *
  7. * In an ideal world, we'd just use Libevent 2.0 from now on. But as of June
  8. * 2009, Libevent 2.0 is still in alpha, and we will have old versions of
  9. * Libevent for the forseeable future.
  10. **/
  11. #include "orconfig.h"
  12. #include "compat.h"
  13. #include "compat_libevent.h"
  14. #include "util.h"
  15. #include "torlog.h"
  16. #ifdef HAVE_EVENT2_EVENT_H
  17. #include <event2/event.h>
  18. #else
  19. #include <event.h>
  20. #endif
  21. /** A number representing a version of Libevent.
  22. This is a 4-byte number, with the first three bytes representing the
  23. major, minor, and patchlevel respectively of the library. The fourth
  24. byte is unused.
  25. This is equivalent to the format of LIBEVENT_VERSION_NUMBER on Libevent
  26. 2.0.1 or later. For versions of Libevent before 1.4.0, which followed the
  27. format of "1.0, 1.0a, 1.0b", we define 1.0 to be equivalent to 1.0.0, 1.0a
  28. to be equivalent to 1.0.1, and so on.
  29. */
  30. typedef uint32_t le_version_t;
  31. /* Macros: returns the number of a libevent version. */
  32. #define V(major, minor, patch) \
  33. (((major) << 24) | ((minor) << 16) | ((patch) << 8))
  34. #define V_OLD(major, minor, patch) \
  35. V((major), (minor), (patch)-'a'+1)
  36. #define LE_OLD V(0,0,0)
  37. #define LE_OTHER V(0,0,99)
  38. static le_version_t tor_get_libevent_version(const char **v_out);
  39. #ifdef HAVE_EVENT_SET_LOG_CALLBACK
  40. /** A string which, if it appears in a libevent log, should be ignored. */
  41. static const char *suppress_msg = NULL;
  42. /** Callback function passed to event_set_log() so we can intercept
  43. * log messages from libevent. */
  44. static void
  45. libevent_logging_callback(int severity, const char *msg)
  46. {
  47. char buf[1024];
  48. size_t n;
  49. if (suppress_msg && strstr(msg, suppress_msg))
  50. return;
  51. n = strlcpy(buf, msg, sizeof(buf));
  52. if (n && n < sizeof(buf) && buf[n-1] == '\n') {
  53. buf[n-1] = '\0';
  54. }
  55. switch (severity) {
  56. case _EVENT_LOG_DEBUG:
  57. log(LOG_DEBUG, LD_NOCB|LD_NET, "Message from libevent: %s", buf);
  58. break;
  59. case _EVENT_LOG_MSG:
  60. log(LOG_INFO, LD_NOCB|LD_NET, "Message from libevent: %s", buf);
  61. break;
  62. case _EVENT_LOG_WARN:
  63. log(LOG_WARN, LD_NOCB|LD_GENERAL, "Warning from libevent: %s", buf);
  64. break;
  65. case _EVENT_LOG_ERR:
  66. log(LOG_ERR, LD_NOCB|LD_GENERAL, "Error from libevent: %s", buf);
  67. break;
  68. default:
  69. log(LOG_WARN, LD_NOCB|LD_GENERAL, "Message [%d] from libevent: %s",
  70. severity, buf);
  71. break;
  72. }
  73. }
  74. /** Set hook to intercept log messages from libevent. */
  75. void
  76. configure_libevent_logging(void)
  77. {
  78. event_set_log_callback(libevent_logging_callback);
  79. }
  80. /** Ignore any libevent log message that contains <b>msg</b>. */
  81. void
  82. suppress_libevent_log_msg(const char *msg)
  83. {
  84. suppress_msg = msg;
  85. }
  86. #else
  87. void
  88. configure_libevent_logging(void)
  89. {
  90. }
  91. void
  92. suppress_libevent_log_msg(const char *msg)
  93. {
  94. (void)msg;
  95. }
  96. #endif
  97. #ifndef HAVE_EVENT2_EVENT_H
  98. /** Work-alike replacement for event_new() on pre-Libevent-2.0 systems. */
  99. struct event *
  100. tor_event_new(struct event_base *base, int sock, short what,
  101. void (*cb)(int, short, void *), void *arg)
  102. {
  103. struct event *e = tor_malloc_zero(sizeof(struct event));
  104. event_set(e, sock, what, cb, arg);
  105. if (! base)
  106. base = tor_libevent_get_base();
  107. event_base_set(base, e);
  108. return e;
  109. }
  110. /** Work-alike replacement for evtimer_new() on pre-Libevent-2.0 systems. */
  111. struct event *
  112. tor_evtimer_new(struct event_base *base,
  113. void (*cb)(int, short, void *), void *arg)
  114. {
  115. return tor_event_new(base, -1, 0, cb, arg);
  116. }
  117. /** Work-alike replacement for evsignal_new() on pre-Libevent-2.0 systems. */
  118. struct event *
  119. tor_evsignal_new(struct event_base * base, int sig,
  120. void (*cb)(int, short, void *), void *arg)
  121. {
  122. return tor_event_new(base, sig, EV_SIGNAL|EV_PERSIST, cb, arg);
  123. }
  124. /** Work-alike replacement for event_free() on pre-Libevent-2.0 systems. */
  125. void
  126. tor_event_free(struct event *ev)
  127. {
  128. event_del(ev);
  129. tor_free(ev);
  130. }
  131. #endif
  132. /** Global event base for use by the main thread. */
  133. struct event_base *the_event_base = NULL;
  134. /* This is what passes for version detection on OSX. We set
  135. * MACOSX_KQUEUE_IS_BROKEN to true iff we're on a version of OSX before
  136. * 10.4.0 (aka 1040). */
  137. #ifdef __APPLE__
  138. #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
  139. #define MACOSX_KQUEUE_IS_BROKEN \
  140. (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1040)
  141. #else
  142. #define MACOSX_KQUEUE_IS_BROKEN 0
  143. #endif
  144. #endif
  145. /** Initialize the Libevent library and set up the event base. */
  146. void
  147. tor_libevent_initialize(tor_libevent_cfg *torcfg)
  148. {
  149. tor_assert(the_event_base == NULL);
  150. /* some paths below don't use torcfg, so avoid unused variable warnings */
  151. (void)torcfg;
  152. #ifdef __APPLE__
  153. if (MACOSX_KQUEUE_IS_BROKEN ||
  154. tor_get_libevent_version(NULL) < V_OLD(1,1,'b')) {
  155. setenv("EVENT_NOKQUEUE","1",1);
  156. }
  157. #endif
  158. #ifdef HAVE_EVENT2_EVENT_H
  159. {
  160. struct event_config *cfg = event_config_new();
  161. #if defined(MS_WINDOWS) && defined(USE_BUFFEREVENTS)
  162. if (! torcfg->disable_iocp)
  163. event_config_set_flag(cfg, EVENT_BASE_FLAG_STARTUP_IOCP);
  164. #endif
  165. #if defined(LIBEVENT_VERSION_NUMBER) && LIBEVENT_VERSION_NUMBER >= V(2,0,7)
  166. if (torcfg->num_cpus > 0)
  167. event_config_set_num_cpus_hint(cfg, torcfg->num_cpus);
  168. #endif
  169. #if LIBEVENT_VERSION_NUMBER >= V(2,0,9)
  170. /* We can enable changelist support with epoll, since we don't give
  171. * Libevent any dup'd fds. This lets us avoid some syscalls. */
  172. event_config_set_flag(cfg, EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST);
  173. #endif
  174. the_event_base = event_base_new_with_config(cfg);
  175. event_config_free(cfg);
  176. }
  177. #else
  178. the_event_base = event_init();
  179. #endif
  180. #if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
  181. /* Making this a NOTICE for now so we can link bugs to a libevent versions
  182. * or methods better. */
  183. log(LOG_NOTICE, LD_GENERAL,
  184. "Initialized libevent version %s using method %s. Good.",
  185. event_get_version(), tor_libevent_get_method());
  186. #else
  187. log(LOG_NOTICE, LD_GENERAL,
  188. "Initialized old libevent (version 1.0b or earlier).");
  189. log(LOG_WARN, LD_GENERAL,
  190. "You have a *VERY* old version of libevent. It is likely to be buggy; "
  191. "please build Tor with a more recent version.");
  192. #endif
  193. }
  194. /** Return the current Libevent event base that we're set up to use. */
  195. struct event_base *
  196. tor_libevent_get_base(void)
  197. {
  198. return the_event_base;
  199. }
  200. #ifndef HAVE_EVENT_BASE_LOOPEXIT
  201. /* Replacement for event_base_loopexit on some very old versions of Libevent
  202. that we are not yet brave enough to deprecate. */
  203. int
  204. tor_event_base_loopexit(struct event_base *base, struct timeval *tv)
  205. {
  206. tor_assert(base == the_event_base);
  207. return event_loopexit(tv);
  208. }
  209. #endif
  210. /** Return the name of the Libevent backend we're using. */
  211. const char *
  212. tor_libevent_get_method(void)
  213. {
  214. #ifdef HAVE_EVENT2_EVENT_H
  215. return event_base_get_method(the_event_base);
  216. #elif defined(HAVE_EVENT_GET_METHOD)
  217. return event_get_method();
  218. #else
  219. return "<unknown>";
  220. #endif
  221. }
  222. /** Return the le_version_t for the current version of libevent. If the
  223. * version is very new, return LE_OTHER. If the version is so old that it
  224. * doesn't support event_get_version(), return LE_OLD. DOCDOC */
  225. static le_version_t
  226. tor_decode_libevent_version(const char *v)
  227. {
  228. unsigned major, minor, patchlevel;
  229. char c, e, extra;
  230. int fields;
  231. /* Try the new preferred "1.4.11-stable" format.
  232. * Also accept "1.4.14b-stable". */
  233. fields = sscanf(v, "%u.%u.%u%c%c", &major, &minor, &patchlevel, &c, &e);
  234. if (fields == 3 ||
  235. ((fields == 4 || fields == 5 ) && (c == '-' || c == '_')) ||
  236. (fields == 5 && TOR_ISALPHA(c) && (e == '-' || e == '_'))) {
  237. return V(major,minor,patchlevel);
  238. }
  239. /* Try the old "1.3e" format. */
  240. fields = sscanf(v, "%u.%u%c%c", &major, &minor, &c, &extra);
  241. if (fields == 3 && TOR_ISALPHA(c)) {
  242. return V_OLD(major, minor, c);
  243. } else if (fields == 2) {
  244. return V(major, minor, 0);
  245. }
  246. return LE_OTHER;
  247. }
  248. /** Return an integer representing the binary interface of a Libevent library.
  249. * Two different versions with different numbers are sure not to be binary
  250. * compatible. Two different versions with the same numbers have a decent
  251. * chance of binary compatibility.*/
  252. static int
  253. le_versions_compatibility(le_version_t v)
  254. {
  255. if (v == LE_OTHER)
  256. return 0;
  257. if (v < V_OLD(1,0,'c'))
  258. return 1;
  259. else if (v < V(1,4,0))
  260. return 2;
  261. else if (v < V(1,4,99))
  262. return 3;
  263. else if (v < V(2,0,1))
  264. return 4;
  265. else /* Everything 2.0 and later should be compatible. */
  266. return 5;
  267. }
  268. /** Return the version number of the currently running version of Libevent.
  269. See le_version_t for info on the format.
  270. */
  271. static le_version_t
  272. tor_get_libevent_version(const char **v_out)
  273. {
  274. const char *v;
  275. le_version_t r;
  276. #if defined(HAVE_EVENT_GET_VERSION_NUMBER)
  277. v = event_get_version();
  278. r = event_get_version_number();
  279. #elif defined (HAVE_EVENT_GET_VERSION)
  280. v = event_get_version();
  281. r = tor_decode_libevent_version(v);
  282. #else
  283. v = "pre-1.0c";
  284. r = LE_OLD;
  285. #endif
  286. if (v_out)
  287. *v_out = v;
  288. return r;
  289. }
  290. /** Return a string representation of the version of the currently running
  291. * version of Libevent. */
  292. const char *
  293. tor_libevent_get_version_str(void)
  294. {
  295. #ifdef HAVE_EVENT_GET_VERSION
  296. return event_get_version();
  297. #else
  298. return "pre-1.0c";
  299. #endif
  300. }
  301. /**
  302. * Compare the current Libevent method and version to a list of versions
  303. * which are known not to work. Warn the user as appropriate.
  304. */
  305. void
  306. tor_check_libevent_version(const char *m, int server,
  307. const char **badness_out)
  308. {
  309. int buggy = 0, iffy = 0, slow = 0, thread_unsafe = 0;
  310. le_version_t version;
  311. const char *v = NULL;
  312. const char *badness = NULL;
  313. const char *sad_os = "";
  314. version = tor_get_libevent_version(&v);
  315. /* It would be better to disable known-buggy methods than to simply
  316. warn about them. However, it's not trivial to get libevent to change its
  317. method once it's initialized, and it's not trivial to tell what method it
  318. will use without initializing it.
  319. If we saw that the version was definitely bad, we could disable all the
  320. methods that were bad for that version. But the issue with that is that
  321. if you've found a libevent before 1.1, you are not at all guaranteed to
  322. have _any_ good method to use.
  323. As of Libevent 2, we can do better, and have more control over what
  324. methods get used. But the problem here is that there are no versions of
  325. Libevent 2 that have buggy event cores, so there's no point in writing
  326. disable code yet.
  327. */
  328. if (!strcmp(m, "kqueue")) {
  329. if (version < V_OLD(1,1,'b'))
  330. buggy = 1;
  331. } else if (!strcmp(m, "epoll")) {
  332. if (version < V(1,1,0))
  333. iffy = 1;
  334. } else if (!strcmp(m, "poll")) {
  335. if (version < V_OLD(1,0,'e'))
  336. buggy = 1;
  337. if (version < V(1,1,0))
  338. slow = 1;
  339. } else if (!strcmp(m, "select")) {
  340. if (version < V(1,1,0))
  341. slow = 1;
  342. } else if (!strcmp(m, "win32")) {
  343. if (version < V_OLD(1,1,'b'))
  344. buggy = 1;
  345. }
  346. /* Libevent versions before 1.3b do very badly on operating systems with
  347. * user-space threading implementations. */
  348. #if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__)
  349. if (server && version < V_OLD(1,3,'b')) {
  350. thread_unsafe = 1;
  351. sad_os = "BSD variants";
  352. }
  353. #elif defined(__APPLE__) || defined(__darwin__)
  354. if (server && version < V_OLD(1,3,'b')) {
  355. thread_unsafe = 1;
  356. sad_os = "Mac OS X";
  357. }
  358. #endif
  359. if (thread_unsafe) {
  360. log(LOG_WARN, LD_GENERAL,
  361. "Libevent version %s often crashes when running a Tor server with %s. "
  362. "Please use the latest version of libevent (1.3b or later)",v,sad_os);
  363. badness = "BROKEN";
  364. } else if (buggy) {
  365. log(LOG_WARN, LD_GENERAL,
  366. "There are serious bugs in using %s with libevent %s. "
  367. "Please use the latest version of libevent.", m, v);
  368. badness = "BROKEN";
  369. } else if (iffy) {
  370. log(LOG_WARN, LD_GENERAL,
  371. "There are minor bugs in using %s with libevent %s. "
  372. "You may want to use the latest version of libevent.", m, v);
  373. badness = "BUGGY";
  374. } else if (slow && server) {
  375. log(LOG_WARN, LD_GENERAL,
  376. "libevent %s can be very slow with %s. "
  377. "When running a server, please use the latest version of libevent.",
  378. v,m);
  379. badness = "SLOW";
  380. }
  381. *badness_out = badness;
  382. }
  383. #if defined(LIBEVENT_VERSION)
  384. #define HEADER_VERSION LIBEVENT_VERSION
  385. #elif defined(_EVENT_VERSION)
  386. #define HEADER_VERSION _EVENT_VERSION
  387. #endif
  388. /** See whether the headers we were built against differ from the library we
  389. * linked against so much that we're likely to crash. If so, warn the
  390. * user. */
  391. void
  392. tor_check_libevent_header_compatibility(void)
  393. {
  394. (void) le_versions_compatibility;
  395. (void) tor_decode_libevent_version;
  396. /* In libevent versions before 2.0, it's hard to keep binary compatibility
  397. * between upgrades, and unpleasant to detect when the version we compiled
  398. * against is unlike the version we have linked against. Here's how. */
  399. #if defined(HEADER_VERSION) && defined(HAVE_EVENT_GET_VERSION)
  400. /* We have a header-file version and a function-call version. Easy. */
  401. if (strcmp(HEADER_VERSION, event_get_version())) {
  402. le_version_t v1, v2;
  403. int compat1 = -1, compat2 = -1;
  404. int verybad;
  405. v1 = tor_decode_libevent_version(HEADER_VERSION);
  406. v2 = tor_decode_libevent_version(event_get_version());
  407. compat1 = le_versions_compatibility(v1);
  408. compat2 = le_versions_compatibility(v2);
  409. verybad = compat1 != compat2;
  410. log(verybad ? LOG_WARN : LOG_NOTICE,
  411. LD_GENERAL, "We were compiled with headers from version %s "
  412. "of Libevent, but we're using a Libevent library that says it's "
  413. "version %s.", HEADER_VERSION, event_get_version());
  414. if (verybad)
  415. log_warn(LD_GENERAL, "This will almost certainly make Tor crash.");
  416. else
  417. log_info(LD_GENERAL, "I think these versions are binary-compatible.");
  418. }
  419. #elif defined(HAVE_EVENT_GET_VERSION)
  420. /* event_get_version but no _EVENT_VERSION. We might be in 1.4.0-beta or
  421. earlier, where that's normal. To see whether we were compiled with an
  422. earlier version, let's see whether the struct event defines MIN_HEAP_IDX.
  423. */
  424. #ifdef HAVE_STRUCT_EVENT_MIN_HEAP_IDX
  425. /* The header files are 1.4.0-beta or later. If the version is not
  426. * 1.4.0-beta, we are incompatible. */
  427. {
  428. if (strcmp(event_get_version(), "1.4.0-beta")) {
  429. log_warn(LD_GENERAL, "It's a little hard to tell, but you seem to have "
  430. "Libevent 1.4.0-beta header files, whereas you have linked "
  431. "against Libevent %s. This will probably make Tor crash.",
  432. event_get_version());
  433. }
  434. }
  435. #else
  436. /* Our headers are 1.3e or earlier. If the library version is not 1.4.x or
  437. later, we're probably fine. */
  438. {
  439. const char *v = event_get_version();
  440. if ((v[0] == '1' && v[2] == '.' && v[3] > '3') || v[0] > '1') {
  441. log_warn(LD_GENERAL, "It's a little hard to tell, but you seem to have "
  442. "Libevent header file from 1.3e or earlier, whereas you have "
  443. "linked against Libevent %s. This will probably make Tor "
  444. "crash.", event_get_version());
  445. }
  446. }
  447. #endif
  448. #elif defined(HEADER_VERSION)
  449. #warn "_EVENT_VERSION is defined but not get_event_version(): Libevent is odd."
  450. #else
  451. /* Your libevent is ancient. */
  452. #endif
  453. }
  454. /*
  455. If possible, we're going to try to use Libevent's periodic timer support,
  456. since it does a pretty good job of making sure that periodic events get
  457. called exactly M seconds apart, rather than starting each one exactly M
  458. seconds after the time that the last one was run.
  459. */
  460. #ifdef HAVE_EVENT2_EVENT_H
  461. #define HAVE_PERIODIC
  462. #define PERIODIC_FLAGS EV_PERSIST
  463. #else
  464. #define PERIODIC_FLAGS 0
  465. #endif
  466. /** Represents a timer that's run every N microseconds by Libevent. */
  467. struct periodic_timer_t {
  468. /** Underlying event used to implement this periodic event. */
  469. struct event *ev;
  470. /** The callback we'll be invoking whenever the event triggers */
  471. void (*cb)(struct periodic_timer_t *, void *);
  472. /** User-supplied data for the callback */
  473. void *data;
  474. #ifndef HAVE_PERIODIC
  475. /** If Libevent doesn't know how to invoke events every N microseconds,
  476. * we'll need to remember the timeout interval here. */
  477. struct timeval tv;
  478. #endif
  479. };
  480. /** Libevent callback to implement a periodic event. */
  481. static void
  482. periodic_timer_cb(evutil_socket_t fd, short what, void *arg)
  483. {
  484. periodic_timer_t *timer = arg;
  485. (void) what;
  486. (void) fd;
  487. #ifndef HAVE_PERIODIC
  488. /** reschedule the event as needed. */
  489. event_add(timer->ev, &timer->tv);
  490. #endif
  491. timer->cb(timer, timer->data);
  492. }
  493. /** Create and schedule a new timer that will run every <b>tv</b> in
  494. * the event loop of <b>base</b>. When the timer fires, it will
  495. * run the timer in <b>cb</b> with the user-supplied data in <b>data</b>. */
  496. periodic_timer_t *
  497. periodic_timer_new(struct event_base *base,
  498. const struct timeval *tv,
  499. void (*cb)(periodic_timer_t *timer, void *data),
  500. void *data)
  501. {
  502. periodic_timer_t *timer;
  503. tor_assert(base);
  504. tor_assert(tv);
  505. tor_assert(cb);
  506. timer = tor_malloc_zero(sizeof(periodic_timer_t));
  507. if (!(timer->ev = tor_event_new(base, -1, PERIODIC_FLAGS,
  508. periodic_timer_cb, timer))) {
  509. tor_free(timer);
  510. return NULL;
  511. }
  512. timer->cb = cb;
  513. timer->data = data;
  514. #ifndef HAVE_PERIODIC
  515. memcpy(&timer->tv, tv, sizeof(struct timeval));
  516. #endif
  517. event_add(timer->ev, (struct timeval *)tv); /*drop const for old libevent*/
  518. return timer;
  519. }
  520. /** Stop and free a periodic timer */
  521. void
  522. periodic_timer_free(periodic_timer_t *timer)
  523. {
  524. if (!timer)
  525. return;
  526. tor_event_free(timer->ev);
  527. tor_free(timer);
  528. }
  529. #ifdef USE_BUFFEREVENTS
  530. static const struct timeval *one_tick = NULL;
  531. /**
  532. * Return a special timeout to be passed whenever libevent's O(1) timeout
  533. * implementation should be used. Only use this when the timer is supposed
  534. * to fire after 1 / TOR_LIBEVENT_TICKS_PER_SECOND seconds have passed.
  535. */
  536. const struct timeval *
  537. tor_libevent_get_one_tick_timeout(void)
  538. {
  539. if (PREDICT_UNLIKELY(one_tick == NULL)) {
  540. struct event_base *base = tor_libevent_get_base();
  541. struct timeval tv;
  542. if (TOR_LIBEVENT_TICKS_PER_SECOND == 1) {
  543. tv.tv_sec = 1;
  544. tv.tv_usec = 0;
  545. } else {
  546. tv.tv_sec = 0;
  547. tv.tv_usec = 1000000 / TOR_LIBEVENT_TICKS_PER_SECOND;
  548. }
  549. one_tick = event_base_init_common_timeout(base, &tv);
  550. }
  551. return one_tick;
  552. }
  553. #endif