periodic.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /* Copyright (c) 2015-2019, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /**
  4. * \file periodic.c
  5. *
  6. * \brief Generic backend for handling periodic events.
  7. *
  8. * The events in this module are used to track items that need
  9. * to fire once every N seconds, possibly picking a new interval each time
  10. * that they fire. See periodic_events[] in mainloop.c for examples.
  11. *
  12. * This module manages a global list of periodic_event_item_t objects,
  13. * each corresponding to a single event. To register an event, pass it to
  14. * periodic_events_add() when initializing your subsystem.
  15. *
  16. * We expect that periodic_event_item_t objects will be statically allocated;
  17. * we set them up and tear them down here, but we don't take ownership of
  18. * them.
  19. */
  20. #include "core/or/or.h"
  21. #include "lib/evloop/compat_libevent.h"
  22. #include "app/config/config.h"
  23. #include "core/mainloop/mainloop.h"
  24. #include "core/mainloop/periodic.h"
  25. #include "lib/evloop/compat_libevent.h"
  26. /** We disable any interval greater than this number of seconds, on the
  27. * grounds that it is probably an absolute time mistakenly passed in as a
  28. * relative time.
  29. */
  30. static const int MAX_INTERVAL = 10 * 365 * 86400;
  31. /**
  32. *
  33. **/
  34. static smartlist_t *the_periodic_events = NULL;
  35. /** Set the event <b>event</b> to run in <b>next_interval</b> seconds from
  36. * now. */
  37. static void
  38. periodic_event_set_interval(periodic_event_item_t *event,
  39. time_t next_interval)
  40. {
  41. tor_assert(next_interval < MAX_INTERVAL);
  42. struct timeval tv;
  43. tv.tv_sec = next_interval;
  44. tv.tv_usec = 0;
  45. mainloop_event_schedule(event->ev, &tv);
  46. }
  47. /** Wraps dispatches for periodic events, <b>data</b> will be a pointer to the
  48. * event that needs to be called */
  49. static void
  50. periodic_event_dispatch(mainloop_event_t *ev, void *data)
  51. {
  52. periodic_event_item_t *event = data;
  53. tor_assert(ev == event->ev);
  54. time_t now = time(NULL);
  55. update_current_time(now);
  56. const or_options_t *options = get_options();
  57. // log_debug(LD_GENERAL, "Dispatching %s", event->name);
  58. int r = event->fn(now, options);
  59. int next_interval = 0;
  60. if (!periodic_event_is_enabled(event)) {
  61. /* The event got disabled from inside its callback, or before: no need to
  62. * reschedule. */
  63. return;
  64. }
  65. /* update the last run time if action was taken */
  66. if (r==0) {
  67. log_err(LD_BUG, "Invalid return value for periodic event from %s.",
  68. event->name);
  69. tor_assert(r != 0);
  70. } else if (r > 0) {
  71. event->last_action_time = now;
  72. /* If the event is meant to happen after ten years, that's likely
  73. * a bug, and somebody gave an absolute time rather than an interval.
  74. */
  75. tor_assert(r < MAX_INTERVAL);
  76. next_interval = r;
  77. } else {
  78. /* no action was taken, it is likely a precondition failed,
  79. * we should reschedule for next second incase the precondition
  80. * passes then */
  81. next_interval = 1;
  82. }
  83. // log_debug(LD_GENERAL, "Scheduling %s for %d seconds", event->name,
  84. // next_interval);
  85. struct timeval tv = { next_interval , 0 };
  86. mainloop_event_schedule(ev, &tv);
  87. }
  88. /** Schedules <b>event</b> to run as soon as possible from now. */
  89. void
  90. periodic_event_reschedule(periodic_event_item_t *event)
  91. {
  92. /* Don't reschedule a disabled or uninitialized event. */
  93. if (event->ev && periodic_event_is_enabled(event)) {
  94. periodic_event_set_interval(event, 1);
  95. }
  96. }
  97. /** Initializes the libevent backend for a periodic event. */
  98. void
  99. periodic_event_setup(periodic_event_item_t *event)
  100. {
  101. if (event->ev) { /* Already setup? This is a bug */
  102. log_err(LD_BUG, "Initial dispatch should only be done once.");
  103. tor_assert(0);
  104. }
  105. event->ev = mainloop_event_new(periodic_event_dispatch,
  106. event);
  107. tor_assert(event->ev);
  108. }
  109. /** Handles initial dispatch for periodic events. It should happen 1 second
  110. * after the events are created to mimic behaviour before #3199's refactor */
  111. void
  112. periodic_event_launch(periodic_event_item_t *event)
  113. {
  114. if (! event->ev) { /* Not setup? This is a bug */
  115. log_err(LD_BUG, "periodic_event_launch without periodic_event_setup");
  116. tor_assert(0);
  117. }
  118. /* Event already enabled? This is a bug */
  119. if (periodic_event_is_enabled(event)) {
  120. log_err(LD_BUG, "periodic_event_launch on an already enabled event");
  121. tor_assert(0);
  122. }
  123. // Initial dispatch
  124. event->enabled = 1;
  125. periodic_event_dispatch(event->ev, event);
  126. }
  127. /** Release all storage associated with <b>event</b> */
  128. void
  129. periodic_event_destroy(periodic_event_item_t *event)
  130. {
  131. if (!event)
  132. return;
  133. mainloop_event_free(event->ev);
  134. event->last_action_time = 0;
  135. }
  136. /** Enable the given event by setting its "enabled" flag and scheduling it to
  137. * run immediately in the event loop. This can be called for an event that is
  138. * already enabled. */
  139. void
  140. periodic_event_enable(periodic_event_item_t *event)
  141. {
  142. tor_assert(event);
  143. /* Safely and silently ignore if this event is already enabled. */
  144. if (periodic_event_is_enabled(event)) {
  145. return;
  146. }
  147. tor_assert(event->ev);
  148. event->enabled = 1;
  149. mainloop_event_activate(event->ev);
  150. }
  151. /** Disable the given event which means the event is destroyed and then the
  152. * event's enabled flag is unset. This can be called for an event that is
  153. * already disabled. */
  154. void
  155. periodic_event_disable(periodic_event_item_t *event)
  156. {
  157. tor_assert(event);
  158. /* Safely and silently ignore if this event is already disabled. */
  159. if (!periodic_event_is_enabled(event)) {
  160. return;
  161. }
  162. mainloop_event_cancel(event->ev);
  163. event->enabled = 0;
  164. }
  165. /**
  166. * Disable an event, then schedule it to run once.
  167. * Do nothing if the event was already disabled.
  168. */
  169. void
  170. periodic_event_schedule_and_disable(periodic_event_item_t *event)
  171. {
  172. tor_assert(event);
  173. if (!periodic_event_is_enabled(event))
  174. return;
  175. periodic_event_disable(event);
  176. mainloop_event_activate(event->ev);
  177. }
  178. /**
  179. * Add <b>item</b> to the list of periodic events.
  180. *
  181. * Note that <b>item</b> should be statically allocated: we do not
  182. * take ownership of it.
  183. **/
  184. void
  185. periodic_events_add(periodic_event_item_t *item)
  186. {
  187. if (!the_periodic_events)
  188. the_periodic_events = smartlist_new();
  189. if (BUG(smartlist_contains(the_periodic_events, item)))
  190. return;
  191. smartlist_add(the_periodic_events, item);
  192. }
  193. /** Set up all not-previously setup periodic events. */
  194. void
  195. periodic_events_setup_all(void)
  196. {
  197. if (! the_periodic_events)
  198. return;
  199. SMARTLIST_FOREACH_BEGIN(the_periodic_events, periodic_event_item_t *, item) {
  200. if (item->ev)
  201. continue;
  202. periodic_event_setup(item);
  203. } SMARTLIST_FOREACH_END(item);
  204. }
  205. /** Reset all the registered periodic events so we'll do all our actions again
  206. * as if we just started up.
  207. *
  208. * Useful if our clock just moved back a long time from the future,
  209. * so we don't wait until that future arrives again before acting.
  210. */
  211. void
  212. periodic_events_reset_all(void)
  213. {
  214. if (! the_periodic_events)
  215. return;
  216. SMARTLIST_FOREACH_BEGIN(the_periodic_events, periodic_event_item_t *, item) {
  217. if (!item->ev)
  218. continue;
  219. periodic_event_reschedule(item);
  220. } SMARTLIST_FOREACH_END(item);
  221. }
  222. /**
  223. * Return the registered periodic event whose name is <b>name</b>.
  224. * Return NULL if no such event is found.
  225. */
  226. periodic_event_item_t *
  227. periodic_events_find(const char *name)
  228. {
  229. if (! the_periodic_events)
  230. return NULL;
  231. SMARTLIST_FOREACH_BEGIN(the_periodic_events, periodic_event_item_t *, item) {
  232. if (strcmp(name, item->name) == 0)
  233. return item;
  234. } SMARTLIST_FOREACH_END(item);
  235. return NULL;
  236. }
  237. /**
  238. * Start or stop registered periodic events, depending on our current set of
  239. * roles.
  240. *
  241. * Invoked when our list of roles, or the net_disabled flag has changed.
  242. **/
  243. void
  244. periodic_events_rescan_by_roles(int roles, bool net_disabled)
  245. {
  246. if (! the_periodic_events)
  247. return;
  248. SMARTLIST_FOREACH_BEGIN(the_periodic_events, periodic_event_item_t *, item) {
  249. if (!item->ev)
  250. continue;
  251. int enable = !!(item->roles & roles);
  252. /* Handle the event flags. */
  253. if (net_disabled &&
  254. (item->flags & PERIODIC_EVENT_FLAG_NEED_NET)) {
  255. enable = 0;
  256. }
  257. /* Enable the event if needed. It is safe to enable an event that was
  258. * already enabled. Same goes for disabling it. */
  259. if (enable) {
  260. log_debug(LD_GENERAL, "Launching periodic event %s", item->name);
  261. periodic_event_enable(item);
  262. } else {
  263. log_debug(LD_GENERAL, "Disabling periodic event %s", item->name);
  264. if (item->flags & PERIODIC_EVENT_FLAG_RUN_ON_DISABLE) {
  265. periodic_event_schedule_and_disable(item);
  266. } else {
  267. periodic_event_disable(item);
  268. }
  269. }
  270. } SMARTLIST_FOREACH_END(item);
  271. }
  272. /** Invoked at shutdown: free resources used in this module.
  273. *
  274. * Does not free the periodic_event_item_t object themselves, because we do
  275. * not own them. */
  276. void
  277. periodic_events_destroy_all(void)
  278. {
  279. if (! the_periodic_events)
  280. return;
  281. SMARTLIST_FOREACH_BEGIN(the_periodic_events, periodic_event_item_t *, item) {
  282. periodic_event_destroy(item);
  283. } SMARTLIST_FOREACH_END(item);
  284. smartlist_free(the_periodic_events);
  285. }
  286. #define LONGEST_TIMER_PERIOD (30 * 86400)
  287. /** Helper: Return the number of seconds between <b>now</b> and <b>next</b>,
  288. * clipped to the range [1 second, LONGEST_TIMER_PERIOD].
  289. *
  290. * We use this to answer the question, "how many seconds is it from now until
  291. * next" in periodic timer callbacks. Don't use it for other purposes
  292. **/
  293. int
  294. safe_timer_diff(time_t now, time_t next)
  295. {
  296. if (next > now) {
  297. /* There were no computers at signed TIME_MIN (1902 on 32-bit systems),
  298. * and nothing that could run Tor. It's a bug if 'next' is around then.
  299. * On 64-bit systems with signed TIME_MIN, TIME_MIN is before the Big
  300. * Bang. We cannot extrapolate past a singularity, but there was probably
  301. * nothing that could run Tor then, either.
  302. **/
  303. tor_assert(next > TIME_MIN + LONGEST_TIMER_PERIOD);
  304. if (next - LONGEST_TIMER_PERIOD > now)
  305. return LONGEST_TIMER_PERIOD;
  306. return (int)(next - now);
  307. } else {
  308. return 1;
  309. }
  310. }