tor  0.4.2.0-alpha-dev
periodic.c
Go to the documentation of this file.
1 /* Copyright (c) 2015-2019, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
3 
27 #include "core/or/or.h"
29 #include "app/config/config.h"
30 #include "core/mainloop/mainloop.h"
31 #include "core/mainloop/periodic.h"
33 
38 static const int MAX_INTERVAL = 10 * 365 * 86400;
39 
45 
48 static void
50  time_t next_interval)
51 {
52  tor_assert(next_interval < MAX_INTERVAL);
53  struct timeval tv;
54  tv.tv_sec = next_interval;
55  tv.tv_usec = 0;
56  mainloop_event_schedule(event->ev, &tv);
57 }
58 
61 static void
63 {
64  periodic_event_item_t *event = data;
65  tor_assert(ev == event->ev);
66 
67  time_t now = time(NULL);
69  const or_options_t *options = get_options();
70 // log_debug(LD_GENERAL, "Dispatching %s", event->name);
71  int r = event->fn(now, options);
72  int next_interval = 0;
73 
74  if (!periodic_event_is_enabled(event)) {
75  /* The event got disabled from inside its callback, or before: no need to
76  * reschedule. */
77  return;
78  }
79 
80  /* update the last run time if action was taken */
81  if (r==0) {
82  log_err(LD_BUG, "Invalid return value for periodic event from %s.",
83  event->name);
84  tor_assert(r != 0);
85  } else if (r > 0) {
86  event->last_action_time = now;
87  /* If the event is meant to happen after ten years, that's likely
88  * a bug, and somebody gave an absolute time rather than an interval.
89  */
91  next_interval = r;
92  } else {
93  /* no action was taken, it is likely a precondition failed,
94  * we should reschedule for next second incase the precondition
95  * passes then */
96  next_interval = 1;
97  }
98 
99 // log_debug(LD_GENERAL, "Scheduling %s for %d seconds", event->name,
100 // next_interval);
101  struct timeval tv = { next_interval , 0 };
102  mainloop_event_schedule(ev, &tv);
103 }
104 
106 void
108 {
109  /* Don't reschedule a disabled or uninitialized event. */
110  if (event->ev && periodic_event_is_enabled(event)) {
111  periodic_event_set_interval(event, 1);
112  }
113 }
114 
117 void
119 {
120  if (event->ev) { /* Already setup? This is a bug */
121  log_err(LD_BUG, "Initial dispatch should only be done once.");
122  tor_assert(0);
123  }
124 
126  event);
127  tor_assert(event->ev);
128 }
129 
132 void
134 {
135  if (! event->ev) { /* Not setup? This is a bug */
136  log_err(LD_BUG, "periodic_event_launch without periodic_event_connect");
137  tor_assert(0);
138  }
139  /* Event already enabled? This is a bug */
140  if (periodic_event_is_enabled(event)) {
141  log_err(LD_BUG, "periodic_event_launch on an already enabled event");
142  tor_assert(0);
143  }
144 
145  // Initial dispatch
146  event->enabled = 1;
147  periodic_event_dispatch(event->ev, event);
148 }
149 
151 static void
153 {
154  if (!event)
155  return;
156  mainloop_event_free(event->ev);
157  event->last_action_time = 0;
158 }
159 
163 void
165 {
166  tor_assert(event);
167  /* Safely and silently ignore if this event is already enabled. */
168  if (periodic_event_is_enabled(event)) {
169  return;
170  }
171 
172  tor_assert(event->ev);
173  event->enabled = 1;
174  mainloop_event_activate(event->ev);
175 }
176 
180 void
182 {
183  tor_assert(event);
184  /* Safely and silently ignore if this event is already disabled. */
185  if (!periodic_event_is_enabled(event)) {
186  return;
187  }
188  mainloop_event_cancel(event->ev);
189  event->enabled = 0;
190 }
191 
196 void
198 {
199  tor_assert(event);
200  if (!periodic_event_is_enabled(event))
201  return;
202 
203  periodic_event_disable(event);
204 
205  mainloop_event_activate(event->ev);
206 }
207 
214 void
216 {
217  if (!the_periodic_events)
218  the_periodic_events = smartlist_new();
219 
220  if (BUG(smartlist_contains(the_periodic_events, item)))
221  return;
222 
224 }
225 
229 void
231 {
232  if (! the_periodic_events)
233  return;
234 
236  if (item->ev)
237  continue;
239  } SMARTLIST_FOREACH_END(item);
240 }
241 
249 void
251 {
252  if (! the_periodic_events)
253  return;
254 
256  if (!item->ev)
257  continue;
258 
260  } SMARTLIST_FOREACH_END(item);
261 }
262 
268 periodic_events_find(const char *name)
269 {
270  if (! the_periodic_events)
271  return NULL;
272 
274  if (strcmp(name, item->name) == 0)
275  return item;
276  } SMARTLIST_FOREACH_END(item);
277  return NULL;
278 }
279 
286 void
287 periodic_events_rescan_by_roles(int roles, bool net_disabled)
288 {
289  if (! the_periodic_events)
290  return;
291 
293  if (!item->ev)
294  continue;
295 
296  int enable = !!(item->roles & roles);
297 
298  /* Handle the event flags. */
299  if (net_disabled &&
300  (item->flags & PERIODIC_EVENT_FLAG_NEED_NET)) {
301  enable = 0;
302  }
303 
304  /* Enable the event if needed. It is safe to enable an event that was
305  * already enabled. Same goes for disabling it. */
306  if (enable) {
307  log_debug(LD_GENERAL, "Launching periodic event %s", item->name);
308  periodic_event_enable(item);
309  } else {
310  log_debug(LD_GENERAL, "Disabling periodic event %s", item->name);
311  if (item->flags & PERIODIC_EVENT_FLAG_RUN_ON_DISABLE) {
313  } else {
315  }
316  }
317  } SMARTLIST_FOREACH_END(item);
318 }
319 
326 void
328 {
329  if (! the_periodic_events)
330  return;
331 
334  } SMARTLIST_FOREACH_END(item);
335 
336  smartlist_free(the_periodic_events);
337 }
338 
339 #define LONGEST_TIMER_PERIOD (30 * 86400)
340 
346 int
347 safe_timer_diff(time_t now, time_t next)
348 {
349  if (next > now) {
350  /* There were no computers at signed TIME_MIN (1902 on 32-bit systems),
351  * and nothing that could run Tor. It's a bug if 'next' is around then.
352  * On 64-bit systems with signed TIME_MIN, TIME_MIN is before the Big
353  * Bang. We cannot extrapolate past a singularity, but there was probably
354  * nothing that could run Tor then, either.
355  **/
356  tor_assert(next > TIME_MIN + LONGEST_TIMER_PERIOD);
357 
358  if (next - LONGEST_TIMER_PERIOD > now)
359  return LONGEST_TIMER_PERIOD;
360  return (int)(next - now);
361  } else {
362  return 1;
363  }
364 }
static const int MAX_INTERVAL
Definition: periodic.c:38
void periodic_events_connect_all(void)
Definition: periodic.c:230
void periodic_event_enable(periodic_event_item_t *event)
Definition: periodic.c:164
static smartlist_t * the_periodic_events
Definition: periodic.c:44
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
void update_current_time(time_t now)
Definition: mainloop.c:2173
#define LD_GENERAL
Definition: log.h:60
void smartlist_add(smartlist_t *sl, void *element)
int smartlist_contains(const smartlist_t *sl, const void *element)
Header file for config.c.
static void periodic_event_set_interval(periodic_event_item_t *event, time_t next_interval)
Definition: periodic.c:49
Header file for mainloop.c.
void mainloop_event_activate(mainloop_event_t *event)
void periodic_events_register(periodic_event_item_t *item)
Definition: periodic.c:215
int safe_timer_diff(time_t now, time_t next)
Definition: periodic.c:347
tor_assert(buffer)
struct mainloop_event_t * ev
Definition: periodic.h:61
static void periodic_event_disconnect(periodic_event_item_t *event)
Definition: periodic.c:152
void mainloop_event_cancel(mainloop_event_t *event)
Master header file for Tor-specific functionality.
void periodic_event_schedule_and_disable(periodic_event_item_t *event)
Definition: periodic.c:197
void periodic_events_reset_all(void)
Definition: periodic.c:250
void periodic_event_reschedule(periodic_event_item_t *event)
Definition: periodic.c:107
void periodic_event_disable(periodic_event_item_t *event)
Definition: periodic.c:181
void periodic_events_disconnect_all(void)
Definition: periodic.c:327
static void periodic_event_dispatch(mainloop_event_t *ev, void *data)
Definition: periodic.c:62
mainloop_event_t * mainloop_event_new(void(*cb)(mainloop_event_t *, void *), void *userdata)
void periodic_event_launch(periodic_event_item_t *event)
Definition: periodic.c:133
int mainloop_event_schedule(mainloop_event_t *event, const struct timeval *tv)
void periodic_event_connect(periodic_event_item_t *event)
Definition: periodic.c:118
Header for compat_libevent.c.
void periodic_events_rescan_by_roles(int roles, bool net_disabled)
Definition: periodic.c:287
periodic_event_item_t * periodic_events_find(const char *name)
Definition: periodic.c:268
#define LD_BUG
Definition: log.h:84