The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
event.h
Go to the documentation of this file.
1 #pragma once
2 /*
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16  */
17 
18 /** Wrapper around libkqueue to make managing events easier
19  *
20  * @file src/lib/util/event.h
21  *
22  * @copyright 2007 The FreeRADIUS server project
23  * @copyright 2007 Alan DeKok (aland@deployingradius.com)
24  */
25 RCSIDH(event_h, "$Id: d3c470a5e7ce5cca84f06a66c28e916759187ee3 $")
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 #include <freeradius-devel/build.h>
32 #include <freeradius-devel/missing.h>
33 #include <freeradius-devel/util/time.h>
34 #include <freeradius-devel/util/talloc.h>
35 
36 #include <stdbool.h>
37 #include <sys/event.h>
38 
39 /** An opaque file descriptor handle
40  */
41 typedef struct fr_event_fd fr_event_fd_t;
42 
43 /** An opaque event list handle
44  */
45 typedef struct fr_event_list fr_event_list_t;
46 
47 /** An opaque timer handle
48  */
49 typedef struct fr_event_timer fr_event_timer_t;
50 
51 /** An opaque PID status handle
52  */
53 typedef struct fr_event_pid fr_event_pid_t;
54 
55 /** An opaquer user event handle
56  */
57 typedef struct fr_event_user_s fr_event_user_t;
58 
59 /** The type of filter to install for an FD
60  */
61 typedef enum {
62  FR_EVENT_FILTER_IO = 1, //!< Combined filter for read/write functions/
63  FR_EVENT_FILTER_VNODE //!< Filter for vnode subfilters
65 
66 /** Operations to perform on filter
67  */
68 typedef enum {
69  FR_EVENT_OP_SUSPEND = 1, //!< Temporarily remove the relevant filter from kevent.
70  FR_EVENT_OP_RESUME //!< Reinsert the filter into kevent.
72 
73 /** Structure describing a modification to a filter's state
74  */
75 typedef struct {
76  size_t offset; //!< Offset of function in func struct.
77  fr_event_op_t op; //!< Operation to perform on function/filter.
79 
80 /** Temporarily remove the filter for a func from kevent
81  *
82  * Use to populate elements in an array of #fr_event_update_t.
83  *
84  @code {.c}
85  static fr_event_update_t pause_read[] = {
86  FR_EVENT_SUSPEND(fr_event_io_func_t, read),
87  { 0 }
88  }
89  @endcode
90  *
91  * @param[in] _s the structure containing the func to suspend.
92  * @param[in] _f the func to suspend.
93  */
94 #define FR_EVENT_SUSPEND(_s, _f) { .offset = offsetof(_s, _f), .op = FR_EVENT_OP_SUSPEND }
95 
96 /** Re-add the filter for a func from kevent
97  *
98  * Use to populate elements in an array of #fr_event_update_t.
99  *
100  @code {.c}
101  static fr_event_update_t resume_read[] = {
102  FR_EVENT_RESUME(fr_event_io_func_t, read),
103  { 0 }
104  }
105  @endcode
106  *
107  * @param[in] _s the structure containing the func to suspend.
108  * @param[in] _f the func to resume.
109  */
110 #define FR_EVENT_RESUME(_s, _f) { .offset = offsetof(_s, _f), .op = FR_EVENT_OP_RESUME }
111 
112 /** Called when a timer event fires
113  *
114  * @param[in] now The current time.
115  * @param[in] el Event list the timer event was inserted into.
116  * @param[in] uctx User ctx passed to #fr_event_timer_in or #fr_event_timer_at.
117  */
118 typedef void (*fr_event_timer_cb_t)(fr_event_list_t *el, fr_time_t now, void *uctx);
119 
120 /** Called after each event loop cycle
121  *
122  * Called before calling kqueue to put the thread in a sleeping state.
123  *
124  * @param[in] now The current time.
125  * @param[in] wake When we'll next need to wake up to service an event.
126  * @param[in] uctx User ctx passed to #fr_event_list_alloc.
127  */
128 typedef int (*fr_event_status_cb_t)(fr_time_t now, fr_time_delta_t wake, void *uctx);
129 
130 /** Called when an IO event occurs on a file descriptor
131  *
132  * @param[in] el Event list the file descriptor was inserted into.
133  * @param[in] fd That experienced the IO event.
134  * @param[in] flags field as returned by kevent.
135  * @param[in] uctx User ctx passed to #fr_event_fd_insert.
136  */
137 typedef void (*fr_event_fd_cb_t)(fr_event_list_t *el, int fd, int flags, void *uctx);
138 
139 /** Called when an IO error event occurs on a file descriptor
140  *
141  * @param[in] el Event list the file descriptor was inserted into.
142  * @param[in] fd That experienced the IO event.
143  * @param[in] flags field as returned by kevent.
144  * @param[in] fd_errno File descriptor error.
145  * @param[in] uctx User ctx passed to #fr_event_fd_insert.
146  */
147 typedef void (*fr_event_error_cb_t)(fr_event_list_t *el, int fd, int flags, int fd_errno, void *uctx);
148 
149 /** Called when a child process has exited
150  *
151  * @param[in] el Event list
152  * @param[in] pid That exited
153  * @param[in] status exit status
154  * @param[in] uctx User ctx passed to #fr_event_fd_insert.
155  */
156 typedef void (*fr_event_pid_cb_t)(fr_event_list_t *el, pid_t pid, int status, void *uctx);
157 
158 /** Called when a user kevent occurs
159  *
160  * @param[in] el Event list
161  * @param[in] uctx User ctx passed to #fr_event_user_insert.
162  */
163 typedef void (*fr_event_user_cb_t)(fr_event_list_t *el, void *uctx);
164 
165 /** Alternative time source, useful for testing
166  *
167  * @return the current time in nanoseconds past the epoch.
168  */
170 
171 /** Callbacks for the #FR_EVENT_FILTER_IO filter
172  */
173 typedef struct {
174  fr_event_fd_cb_t read; //!< Callback for when data is available.
175  fr_event_fd_cb_t write; //!< Callback for when we can write data.
177 
178 /** Callbacks for the #FR_EVENT_FILTER_VNODE filter
179  */
180 typedef struct {
181  fr_event_fd_cb_t delete; //!< The file was deleted.
182  fr_event_fd_cb_t write; //!< The file was written to.
183  fr_event_fd_cb_t extend; //!< Additional files were added to a directory.
184  fr_event_fd_cb_t attrib; //!< File attributes changed.
185  fr_event_fd_cb_t link; //!< The link count on the file changed.
186  fr_event_fd_cb_t rename; //!< The file was renamed.
187 #ifdef NOTE_REVOKE
188  fr_event_fd_cb_t revoke; //!< Volume containing the file was unmounted or
189  ///< access was revoked with revoke().
190 #endif
191 #ifdef NOTE_FUNLOCK
192  fr_event_fd_cb_t funlock; //!< The file was unlocked.
193 #endif
195 
196 /** Union of all filter functions
197  */
198 typedef union {
199  fr_event_io_func_t io; //!< Read/write functions.
200  fr_event_vnode_func_t vnode; //!< vnode callback functions.
202 
207 
209  fr_event_list_t *dst, fr_event_list_t *src, int fd, fr_event_filter_t filter);
210 #define fr_event_fd_mode(...) _fr_event_fd_move(NDEBUG_LOCATION_EXP __VA_ARGS__)
211 
213  TALLOC_CTX *ctx, fr_event_fd_t **ef_out,
214  fr_event_list_t *el, int fd,
215  fr_event_filter_t filter,
216  void *funcs,
217  fr_event_error_cb_t error,
218  void *uctx);
219 #define fr_event_filter_insert(...) _fr_event_filter_insert(NDEBUG_LOCATION_EXP __VA_ARGS__)
220 
222  fr_event_list_t *el, int fd, fr_event_filter_t filter,
223  fr_event_update_t const updates[]);
224 #define fr_event_filter_update(...) _fr_event_filter_update(NDEBUG_LOCATION_EXP __VA_ARGS__)
225 
227  TALLOC_CTX *ctx, fr_event_fd_t **ef_out, fr_event_list_t *el, int fd,
228  fr_event_fd_cb_t read_fn,
229  fr_event_fd_cb_t write_fn,
230  fr_event_error_cb_t error,
231  void *uctx);
232 #define fr_event_fd_insert(...) _fr_event_fd_insert(NDEBUG_LOCATION_EXP __VA_ARGS__)
233 
235 
237 
238 fr_event_fd_cb_t fr_event_fd_cb(fr_event_fd_t *ef, int filter, int fflags);
239 
241 
242 #ifndef NDEBUG
243 int fr_event_fd_armour(fr_event_list_t *el, int fd, fr_event_filter_t, uintptr_t armour);
244 int fr_event_fd_unarmour(fr_event_list_t *el, int fd, fr_event_filter_t filter, uintptr_t armour);
245 #endif
246 
248  TALLOC_CTX *ctx, fr_event_list_t *el, fr_event_timer_t const **ev,
249  fr_time_t when, fr_event_timer_cb_t callback, void const *uctx);
250 #define fr_event_timer_at(...) _fr_event_timer_at(NDEBUG_LOCATION_EXP __VA_ARGS__)
251 
253  TALLOC_CTX *ctx, fr_event_list_t *el, fr_event_timer_t const **ev,
254  fr_time_delta_t delta, fr_event_timer_cb_t callback, void const *uctx);
255 #define fr_event_timer_in(...) _fr_event_timer_in(NDEBUG_LOCATION_EXP __VA_ARGS__)
256 
258 
260 
262  TALLOC_CTX *ctx, fr_event_list_t *el, fr_event_pid_t const **ev_p,
263  pid_t pid, fr_event_pid_cb_t wait_fn, void *uctx)
264  CC_HINT(nonnull(NDEBUG_LOCATION_NONNULL(2)));
265 #define fr_event_pid_wait(...) _fr_event_pid_wait(NDEBUG_LOCATION_EXP __VA_ARGS__)
266 
268  fr_event_list_t *el, pid_t pid,
269  fr_event_pid_cb_t wait_fn, void *uctx)
270  CC_HINT(nonnull(NDEBUG_LOCATION_NONNULL(1)));
271 #define fr_event_pid_reap(...) _fr_event_pid_reap(NDEBUG_LOCATION_EXP __VA_ARGS__)
272 
274 
276 
278  TALLOC_CTX *ctx, fr_event_list_t *el, fr_event_user_t **ev_p,
279  bool trigger, fr_event_user_cb_t callback, void *uctx);
280 #define fr_event_user_insert(_ctx, _ev_p, _el, _trigger, _callback, _uctx) \
281  _fr_event_user_insert(NDEBUG_LOCATION_EXP _ctx, _ev_p, _el, _trigger, _callback, _uctx)
282 
284 
285 int fr_event_user_delete(fr_event_list_t *el, fr_event_user_cb_t user, void *uctx) CC_HINT(nonnull(1,2));
286 
287 int fr_event_pre_insert(fr_event_list_t *el, fr_event_status_cb_t callback, void *uctx) CC_HINT(nonnull(1,2));
288 int fr_event_pre_delete(fr_event_list_t *el, fr_event_status_cb_t callback, void *uctx) CC_HINT(nonnull(1,2));
289 
290 int fr_event_post_insert(fr_event_list_t *el, fr_event_timer_cb_t callback, void *uctx) CC_HINT(nonnull(1,2));
291 int fr_event_post_delete(fr_event_list_t *el, fr_event_timer_cb_t callback, void *uctx) CC_HINT(nonnull(1,2));
292 
293 int fr_event_corral(fr_event_list_t *el, fr_time_t now, bool wait);
295 
296 void fr_event_loop_exit(fr_event_list_t *el, int code);
299 
300 fr_event_list_t *fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_cb_t status, void *status_ctx);
302 
304 
305 #ifdef WITH_EVENT_DEBUG
306 void fr_event_report(fr_event_list_t *el, fr_time_t now, void *uctx);
307 # ifndef NDEBUG
308 void fr_event_timer_dump(fr_event_list_t *el);
309 # endif
310 #endif
311 
312 #ifdef __cplusplus
313 }
314 #endif
#define RCSIDH(h, id)
Definition: build.h:445
#define NDEBUG_LOCATION_ARGS
Pass caller information to the function.
Definition: build.h:261
#define NDEBUG_LOCATION_NONNULL(_num)
Definition: build.h:264
static fr_time_delta_t timeout
Definition: dhcpclient.c:54
int fr_event_pre_delete(fr_event_list_t *el, fr_event_status_cb_t callback, void *uctx))
Delete a pre-event callback from the event list.
Definition: event.c:2274
void fr_event_service(fr_event_list_t *el)
Service any outstanding timer or file descriptor events.
Definition: event.c:2542
int fr_event_timer_delete(fr_event_timer_t const **ev)
Delete a timer event from the event list.
Definition: event.c:1604
int fr_event_post_delete(fr_event_list_t *el, fr_event_timer_cb_t callback, void *uctx))
Delete a post-event callback from the event list.
Definition: event.c:2328
fr_event_fd_cb_t write
The file was written to.
Definition: event.h:182
int fr_event_pre_insert(fr_event_list_t *el, fr_event_status_cb_t callback, void *uctx))
Add a pre-event callback to the event list.
Definition: event.c:2252
fr_event_io_func_t io
Read/write functions.
Definition: event.h:199
void(* fr_event_timer_cb_t)(fr_event_list_t *el, fr_time_t now, void *uctx)
Called when a timer event fires.
Definition: event.h:118
fr_time_t fr_event_list_time(fr_event_list_t *el)
Get the current server time according to the event list.
Definition: event.c:636
fr_time_t fr_event_timer_when(fr_event_timer_t const *ev)
Internal timestamp representing when the timer should fire.
Definition: event.c:1626
void fr_event_list_set_time_func(fr_event_list_t *el, fr_event_time_source_t func)
Override event list time source.
Definition: event.c:2964
fr_event_fd_cb_t attrib
File attributes changed.
Definition: event.h:184
fr_event_fd_cb_t link
The link count on the file changed.
Definition: event.h:185
void(* fr_event_fd_cb_t)(fr_event_list_t *el, int fd, int flags, void *uctx)
Called when an IO event occurs on a file descriptor.
Definition: event.h:137
fr_event_op_t
Operations to perform on filter.
Definition: event.h:68
@ FR_EVENT_OP_SUSPEND
Temporarily remove the relevant filter from kevent.
Definition: event.h:69
@ FR_EVENT_OP_RESUME
Reinsert the filter into kevent.
Definition: event.h:70
int _fr_event_user_insert(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, fr_event_list_t *el, fr_event_user_t **ev_p, bool trigger, fr_event_user_cb_t callback, void *uctx)
Add a user callback to the event list.
Definition: event.c:2180
fr_event_filter_t
The type of filter to install for an FD.
Definition: event.h:61
@ FR_EVENT_FILTER_VNODE
Filter for vnode subfilters.
Definition: event.h:63
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
Definition: event.h:62
size_t offset
Offset of function in func struct.
Definition: event.h:76
fr_event_list_t * fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_cb_t status, void *status_ctx)
Initialise a new event list.
Definition: event.c:2892
int fr_event_corral(fr_event_list_t *el, fr_time_t now, bool wait)
Gather outstanding timer and file descriptor events.
Definition: event.c:2407
fr_event_fd_cb_t rename
The file was renamed.
Definition: event.h:186
int _fr_event_timer_at(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, fr_event_list_t *el, fr_event_timer_t const **ev, fr_time_t when, fr_event_timer_cb_t callback, void const *uctx)
Insert a timer event into an event list.
Definition: event.c:1444
uint64_t fr_event_list_num_timers(fr_event_list_t *el)
Return the number of timer events currently scheduled.
Definition: event.c:606
int fr_event_user_trigger(fr_event_list_t *el, fr_event_user_t *ev)
Trigger a user event.
Definition: event.c:2226
void * fr_event_fd_uctx(fr_event_fd_t *ef)
Returns the uctx associated with an fr_event_fd_t handle.
Definition: event.c:1319
int fr_event_fd_unarmour(fr_event_list_t *el, int fd, fr_event_filter_t filter, uintptr_t armour)
Unarmour an FD.
Definition: event.c:1365
int _fr_event_pid_reap(NDEBUG_LOCATION_ARGS fr_event_list_t *el, pid_t pid, fr_event_pid_cb_t wait_fn, void *uctx)))
Asynchronously wait for a PID to exit, then reap it.
Definition: event.c:1961
uint64_t fr_event_list_num_fds(fr_event_list_t *el)
Return the number of file descriptors is_registered with this event loop.
Definition: event.c:594
fr_event_fd_cb_t read
Callback for when data is available.
Definition: event.h:174
void(* fr_event_pid_cb_t)(fr_event_list_t *el, pid_t pid, int status, void *uctx)
Called when a child process has exited.
Definition: event.h:156
void(* fr_event_error_cb_t)(fr_event_list_t *el, int fd, int flags, int fd_errno, void *uctx)
Called when an IO error event occurs on a file descriptor.
Definition: event.h:147
int fr_event_list_kq(fr_event_list_t *el)
Return the kq associated with an event list.
Definition: event.c:618
fr_event_fd_cb_t write
Callback for when we can write data.
Definition: event.h:175
fr_event_vnode_func_t vnode
vnode callback functions.
Definition: event.h:200
int fr_event_fd_armour(fr_event_list_t *el, int fd, fr_event_filter_t, uintptr_t armour)
Armour an FD.
Definition: event.c:1335
bool fr_event_list_empty(fr_event_list_t *el)
Return whether the event loop has any active events.
Definition: event.c:2972
unsigned int fr_event_list_reap_signal(fr_event_list_t *el, fr_time_delta_t timeout, int signal)
Send a signal to all the processes we have in our reap list, and reap them.
Definition: event.c:1997
int _fr_event_timer_in(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, fr_event_list_t *el, fr_event_timer_t const **ev, fr_time_delta_t delta, fr_event_timer_cb_t callback, void const *uctx)
Insert a timer event into an event list.
Definition: event.c:1589
bool fr_event_loop_exiting(fr_event_list_t *el)
Check to see whether the event loop is in the process of exiting.
Definition: event.c:2748
int _fr_event_filter_update(NDEBUG_LOCATION_ARGS fr_event_list_t *el, int fd, fr_event_filter_t filter, fr_event_update_t const updates[])
Suspend/resume a subset of filters.
Definition: event.c:993
fr_time_t(* fr_event_time_source_t)(void)
Alternative time source, useful for testing.
Definition: event.h:169
int _fr_event_fd_move(NDEBUG_LOCATION_ARGS fr_event_list_t *dst, fr_event_list_t *src, int fd, fr_event_filter_t filter)
Move a file descriptor event from one event list to another.
Definition: event.c:942
int _fr_event_fd_insert(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, fr_event_fd_t **ef_out, fr_event_list_t *el, int fd, fr_event_fd_cb_t read_fn, fr_event_fd_cb_t write_fn, fr_event_error_cb_t error, void *uctx)
Associate I/O callbacks with a file descriptor.
Definition: event.c:1226
int fr_event_timer_run(fr_event_list_t *el, fr_time_t *when)
Run a single scheduled timer event.
Definition: event.c:2356
int(* fr_event_status_cb_t)(fr_time_t now, fr_time_delta_t wake, void *uctx)
Called after each event loop cycle.
Definition: event.h:128
fr_event_op_t op
Operation to perform on function/filter.
Definition: event.h:77
int fr_event_user_delete(fr_event_list_t *el, fr_event_user_cb_t user, void *uctx))
void fr_event_loop_exit(fr_event_list_t *el, int code)
Signal an event loop exit with the specified code.
Definition: event.c:2737
int _fr_event_pid_wait(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, fr_event_list_t *el, fr_event_pid_t const **ev_p, pid_t pid, fr_event_pid_cb_t wait_fn, void *uctx)))
Insert a PID event into an event list.
Definition: event.c:1734
void(* fr_event_user_cb_t)(fr_event_list_t *el, void *uctx)
Called when a user kevent occurs.
Definition: event.h:163
fr_event_fd_cb_t extend
Additional files were added to a directory.
Definition: event.h:183
int fr_event_fd_delete(fr_event_list_t *el, int fd, fr_event_filter_t filter)
Remove a file descriptor from the event loop.
Definition: event.c:1253
int fr_event_loop(fr_event_list_t *el)
Run an event loop.
Definition: event.c:2759
fr_event_fd_cb_t fr_event_fd_cb(fr_event_fd_t *ef, int filter, int fflags)
Returns the appropriate callback function for a given event.
Definition: event.c:1311
int _fr_event_filter_insert(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, fr_event_fd_t **ef_out, fr_event_list_t *el, int fd, fr_event_filter_t filter, void *funcs, fr_event_error_cb_t error, void *uctx)
Insert a filter for the specified fd.
Definition: event.c:1070
int fr_event_post_insert(fr_event_list_t *el, fr_event_timer_cb_t callback, void *uctx))
Add a post-event callback to the event list.
Definition: event.c:2306
fr_event_fd_t * fr_event_fd_handle(fr_event_list_t *el, int fd, fr_event_filter_t filter)
Get the opaque event handle from a file descriptor.
Definition: event.c:1289
Callbacks for the FR_EVENT_FILTER_IO filter.
Definition: event.h:173
Structure describing a modification to a filter's state.
Definition: event.h:75
Callbacks for the FR_EVENT_FILTER_VNODE filter.
Definition: event.h:180
Union of all filter functions.
Definition: event.h:198
A file descriptor/filter event.
Definition: event.c:294
Stores all information relating to an event list.
Definition: event.c:411
A timer event.
Definition: event.c:102
Callbacks for kevent() user events.
Definition: event.c:375
struct fr_time_s fr_time_t
"server local" time.
A time delta, a difference in time measured in nanoseconds.
Definition: time.h:80
"server local" time.
Definition: time.h:69
static fr_event_list_t * el
int nonnull(2, 5))