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