change Christinas previous patch to only perform the check/logging
[sahlberg/ctdb.git] / lib / tevent / tevent_standard.c
1 /*
2    Unix SMB/CIFS implementation.
3    main select loop and event handling
4    Copyright (C) Andrew Tridgell        2003-2005
5    Copyright (C) Stefan Metzmacher      2005-2009
6
7      ** NOTE! The following LGPL license applies to the tevent
8      ** library. This does NOT imply that all of Samba is released
9      ** under the LGPL
10
11    This library is free software; you can redistribute it and/or
12    modify it under the terms of the GNU Lesser General Public
13    License as published by the Free Software Foundation; either
14    version 3 of the License, or (at your option) any later version.
15
16    This library is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    Lesser General Public License for more details.
20
21    You should have received a copy of the GNU Lesser General Public
22    License along with this library; if not, see <http://www.gnu.org/licenses/>.
23 */
24
25 /*
26   This is SAMBA's default event loop code
27
28   - we try to use epoll if configure detected support for it
29     otherwise we use select()
30   - if epoll is broken on the system or the kernel doesn't support it
31     at runtime we fallback to select()
32 */
33
34 #include "replace.h"
35 #include "system/filesys.h"
36 #include "system/select.h"
37 #include "tevent.h"
38 #include "tevent_util.h"
39 #include "tevent_internal.h"
40
41 struct std_event_context {
42         /* a pointer back to the generic event_context */
43         struct tevent_context *ev;
44
45         /* the maximum file descriptor number in fd_events */
46         int maxfd;
47
48         /* information for exiting from the event loop */
49         int exit_code;
50
51         /* when using epoll this is the handle from epoll_create */
52         int epoll_fd;
53
54         /* our pid at the time the epoll_fd was created */
55         pid_t pid;
56 };
57
58 /* use epoll if it is available */
59 #if HAVE_EPOLL
60 /*
61   called when a epoll call fails, and we should fallback
62   to using select
63 */
64 static void epoll_fallback_to_select(struct std_event_context *std_ev, const char *reason)
65 {
66         tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
67                      "%s (%s) - falling back to select()\n",
68                      reason, strerror(errno));
69         close(std_ev->epoll_fd);
70         std_ev->epoll_fd = -1;
71         talloc_set_destructor(std_ev, NULL);
72 }
73
74 /*
75   map from TEVENT_FD_* to EPOLLIN/EPOLLOUT
76 */
77 static uint32_t epoll_map_flags(uint16_t flags)
78 {
79         uint32_t ret = 0;
80         if (flags & TEVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP);
81         if (flags & TEVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP);
82         return ret;
83 }
84
85 /*
86  free the epoll fd
87 */
88 static int epoll_ctx_destructor(struct std_event_context *std_ev)
89 {
90         if (std_ev->epoll_fd != -1) {
91                 close(std_ev->epoll_fd);
92         }
93         std_ev->epoll_fd = -1;
94         return 0;
95 }
96
97 /*
98  init the epoll fd
99 */
100 static void epoll_init_ctx(struct std_event_context *std_ev)
101 {
102         std_ev->epoll_fd = epoll_create(64);
103         std_ev->pid = getpid();
104         talloc_set_destructor(std_ev, epoll_ctx_destructor);
105 }
106
107 static void epoll_add_event(struct std_event_context *std_ev, struct tevent_fd *fde);
108
109 /*
110   reopen the epoll handle when our pid changes
111   see http://junkcode.samba.org/ftp/unpacked/junkcode/epoll_fork.c for an
112   demonstration of why this is needed
113  */
114 static void epoll_check_reopen(struct std_event_context *std_ev)
115 {
116         struct tevent_fd *fde;
117
118         if (std_ev->pid == getpid()) {
119                 return;
120         }
121
122         close(std_ev->epoll_fd);
123         std_ev->epoll_fd = epoll_create(64);
124         if (std_ev->epoll_fd == -1) {
125                 tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
126                              "Failed to recreate epoll handle after fork\n");
127                 return;
128         }
129         std_ev->pid = getpid();
130         for (fde=std_ev->ev->fd_events;fde;fde=fde->next) {
131                 epoll_add_event(std_ev, fde);
132         }
133 }
134
135 #define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT      (1<<0)
136 #define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR   (1<<1)
137 #define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR      (1<<2)
138
139 /*
140  add the epoll event to the given fd_event
141 */
142 static void epoll_add_event(struct std_event_context *std_ev, struct tevent_fd *fde)
143 {
144         struct epoll_event event;
145         if (std_ev->epoll_fd == -1) return;
146
147         fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
148
149         /* if we don't want events yet, don't add an epoll_event */
150         if (fde->flags == 0) return;
151
152         ZERO_STRUCT(event);
153         event.events = epoll_map_flags(fde->flags);
154         event.data.ptr = fde;
155         if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event) != 0) {
156                 epoll_fallback_to_select(std_ev, "EPOLL_CTL_ADD failed");
157         }
158         fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
159
160         /* only if we want to read we want to tell the event handler about errors */
161         if (fde->flags & TEVENT_FD_READ) {
162                 fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
163         }
164 }
165
166 /*
167  delete the epoll event for given fd_event
168 */
169 static void epoll_del_event(struct std_event_context *std_ev, struct tevent_fd *fde)
170 {
171         struct epoll_event event;
172         if (std_ev->epoll_fd == -1) return;
173
174         fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
175
176         /* if there's no epoll_event, we don't need to delete it */
177         if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT)) return;
178
179         ZERO_STRUCT(event);
180         event.events = epoll_map_flags(fde->flags);
181         event.data.ptr = fde;
182         epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event);
183         fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
184 }
185
186 /*
187  change the epoll event to the given fd_event
188 */
189 static void epoll_mod_event(struct std_event_context *std_ev, struct tevent_fd *fde)
190 {
191         struct epoll_event event;
192         if (std_ev->epoll_fd == -1) return;
193
194         fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
195
196         ZERO_STRUCT(event);
197         event.events = epoll_map_flags(fde->flags);
198         event.data.ptr = fde;
199         if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) {
200                 epoll_fallback_to_select(std_ev, "EPOLL_CTL_MOD failed");
201         }
202
203         /* only if we want to read we want to tell the event handler about errors */
204         if (fde->flags & TEVENT_FD_READ) {
205                 fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
206         }
207 }
208
209 static void epoll_change_event(struct std_event_context *std_ev, struct tevent_fd *fde)
210 {
211         bool got_error = (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR);
212         bool want_read = (fde->flags & TEVENT_FD_READ);
213         bool want_write= (fde->flags & TEVENT_FD_WRITE);
214
215         if (std_ev->epoll_fd == -1) return;
216
217         fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
218
219         /* there's already an event */
220         if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT) {
221                 if (want_read || (want_write && !got_error)) {
222                         epoll_mod_event(std_ev, fde);
223                         return;
224                 }
225                 /*
226                  * if we want to match the select behavior, we need to remove the epoll_event
227                  * when the caller isn't interested in events.
228                  *
229                  * this is because epoll reports EPOLLERR and EPOLLHUP, even without asking for them
230                  */
231                 epoll_del_event(std_ev, fde);
232                 return;
233         }
234
235         /* there's no epoll_event attached to the fde */
236         if (want_read || (want_write && !got_error)) {
237                 epoll_add_event(std_ev, fde);
238                 return;
239         }
240 }
241
242 extern pid_t ctdbd_pid;
243
244 /*
245   event loop handling using epoll
246 */
247 static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tvalp)
248 {
249         int ret, i;
250 #define MAXEVENTS 1
251         struct epoll_event events[MAXEVENTS];
252         int timeout = -1;
253
254         if (std_ev->epoll_fd == -1) return -1;
255
256         if (tvalp) {
257                 /* it's better to trigger timed events a bit later than to early */
258                 timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
259         }
260
261         if (std_ev->ev->signal_events &&
262             tevent_common_check_signal(std_ev->ev)) {
263                 return 0;
264         }
265
266         if (getpid() == ctdbd_pid) tevent_before_wait(std_ev->ev);
267         ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout);
268         if (getpid() == ctdbd_pid) tevent_after_wait(std_ev->ev);
269
270         if (ret == -1 && errno == EINTR && std_ev->ev->signal_events) {
271                 if (tevent_common_check_signal(std_ev->ev)) {
272                         return 0;
273                 }
274         }
275
276         if (ret == -1 && errno != EINTR) {
277                 epoll_fallback_to_select(std_ev, "epoll_wait() failed");
278                 return -1;
279         }
280
281         if (ret == 0 && tvalp) {
282                 /* we don't care about a possible delay here */
283                 tevent_common_loop_timer_delay(std_ev->ev);
284                 return 0;
285         }
286
287         for (i=0;i<ret;i++) {
288                 struct tevent_fd *fde = talloc_get_type(events[i].data.ptr,
289                                                        struct tevent_fd);
290                 uint16_t flags = 0;
291
292                 if (fde == NULL) {
293                         epoll_fallback_to_select(std_ev, "epoll_wait() gave bad data");
294                         return -1;
295                 }
296                 if (events[i].events & (EPOLLHUP|EPOLLERR)) {
297                         fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR;
298                         /*
299                          * if we only wait for TEVENT_FD_WRITE, we should not tell the
300                          * event handler about it, and remove the epoll_event,
301                          * as we only report errors when waiting for read events,
302                          * to match the select() behavior
303                          */
304                         if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) {
305                                 epoll_del_event(std_ev, fde);
306                                 continue;
307                         }
308                         flags |= TEVENT_FD_READ;
309                 }
310                 if (events[i].events & EPOLLIN) flags |= TEVENT_FD_READ;
311                 if (events[i].events & EPOLLOUT) flags |= TEVENT_FD_WRITE;
312                 if (flags) {
313                         fde->handler(std_ev->ev, fde, flags, fde->private_data);
314                         break;
315                 }
316         }
317
318         return 0;
319 }
320 #else
321 #define epoll_init_ctx(std_ev)
322 #define epoll_add_event(std_ev,fde)
323 #define epoll_del_event(std_ev,fde)
324 #define epoll_change_event(std_ev,fde)
325 #define epoll_event_loop(std_ev,tvalp) (-1)
326 #define epoll_check_reopen(std_ev)
327 #endif
328
329 /*
330   create a std_event_context structure.
331 */
332 static int std_event_context_init(struct tevent_context *ev)
333 {
334         struct std_event_context *std_ev;
335
336         std_ev = talloc_zero(ev, struct std_event_context);
337         if (!std_ev) return -1;
338         std_ev->ev = ev;
339         std_ev->epoll_fd = -1;
340
341         epoll_init_ctx(std_ev);
342
343         ev->additional_data = std_ev;
344         return 0;
345 }
346
347 /*
348   recalculate the maxfd
349 */
350 static void calc_maxfd(struct std_event_context *std_ev)
351 {
352         struct tevent_fd *fde;
353
354         std_ev->maxfd = 0;
355         for (fde = std_ev->ev->fd_events; fde; fde = fde->next) {
356                 if (fde->fd > std_ev->maxfd) {
357                         std_ev->maxfd = fde->fd;
358                 }
359         }
360 }
361
362
363 /* to mark the ev->maxfd invalid
364  * this means we need to recalculate it
365  */
366 #define EVENT_INVALID_MAXFD (-1)
367
368 /*
369   destroy an fd_event
370 */
371 static int std_event_fd_destructor(struct tevent_fd *fde)
372 {
373         struct tevent_context *ev = fde->event_ctx;
374         struct std_event_context *std_ev = NULL;
375
376         if (ev) {
377                 std_ev = talloc_get_type(ev->additional_data,
378                                          struct std_event_context);
379
380                 epoll_check_reopen(std_ev);
381
382                 if (std_ev->maxfd == fde->fd) {
383                         std_ev->maxfd = EVENT_INVALID_MAXFD;
384                 }
385
386                 epoll_del_event(std_ev, fde);
387         }
388
389         return tevent_common_fd_destructor(fde);
390 }
391
392 /*
393   add a fd based event
394   return NULL on failure (memory allocation error)
395 */
396 static struct tevent_fd *std_event_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx,
397                                           int fd, uint16_t flags,
398                                           tevent_fd_handler_t handler,
399                                           void *private_data,
400                                           const char *handler_name,
401                                           const char *location)
402 {
403         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
404                                                            struct std_event_context);
405         struct tevent_fd *fde;
406
407         epoll_check_reopen(std_ev);
408
409         fde = tevent_common_add_fd(ev, mem_ctx, fd, flags,
410                                    handler, private_data,
411                                    handler_name, location);
412         if (!fde) return NULL;
413
414         if ((std_ev->maxfd != EVENT_INVALID_MAXFD)
415             && (fde->fd > std_ev->maxfd)) {
416                 std_ev->maxfd = fde->fd;
417         }
418         talloc_set_destructor(fde, std_event_fd_destructor);
419
420         epoll_add_event(std_ev, fde);
421
422         return fde;
423 }
424
425 /*
426   set the fd event flags
427 */
428 static void std_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
429 {
430         struct tevent_context *ev;
431         struct std_event_context *std_ev;
432
433         if (fde->flags == flags) return;
434
435         ev = fde->event_ctx;
436         std_ev = talloc_get_type(ev->additional_data, struct std_event_context);
437
438         fde->flags = flags;
439
440         epoll_check_reopen(std_ev);
441
442         epoll_change_event(std_ev, fde);
443 }
444
445 /*
446   event loop handling using select()
447 */
448 static int std_event_loop_select(struct std_event_context *std_ev, struct timeval *tvalp)
449 {
450         fd_set r_fds, w_fds;
451         struct tevent_fd *fde;
452         int selrtn;
453
454         /* we maybe need to recalculate the maxfd */
455         if (std_ev->maxfd == EVENT_INVALID_MAXFD) {
456                 calc_maxfd(std_ev);
457         }
458
459         FD_ZERO(&r_fds);
460         FD_ZERO(&w_fds);
461
462         /* setup any fd events */
463         for (fde = std_ev->ev->fd_events; fde; fde = fde->next) {
464                 if (fde->flags & TEVENT_FD_READ) {
465                         FD_SET(fde->fd, &r_fds);
466                 }
467                 if (fde->flags & TEVENT_FD_WRITE) {
468                         FD_SET(fde->fd, &w_fds);
469                 }
470         }
471
472         if (std_ev->ev->signal_events &&
473             tevent_common_check_signal(std_ev->ev)) {
474                 return 0;
475         }
476
477         selrtn = select(std_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
478
479         if (selrtn == -1 && errno == EINTR &&
480             std_ev->ev->signal_events) {
481                 tevent_common_check_signal(std_ev->ev);
482                 return 0;
483         }
484
485         if (selrtn == -1 && errno == EBADF) {
486                 /* the socket is dead! this should never
487                    happen as the socket should have first been
488                    made readable and that should have removed
489                    the event, so this must be a bug. This is a
490                    fatal error. */
491                 tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
492                              "ERROR: EBADF on std_event_loop_once\n");
493                 std_ev->exit_code = EBADF;
494                 return -1;
495         }
496
497         if (selrtn == 0 && tvalp) {
498                 /* we don't care about a possible delay here */
499                 tevent_common_loop_timer_delay(std_ev->ev);
500                 return 0;
501         }
502
503         if (selrtn > 0) {
504                 /* at least one file descriptor is ready - check
505                    which ones and call the handler, being careful to allow
506                    the handler to remove itself when called */
507                 for (fde = std_ev->ev->fd_events; fde; fde = fde->next) {
508                         uint16_t flags = 0;
509
510                         if (FD_ISSET(fde->fd, &r_fds)) flags |= TEVENT_FD_READ;
511                         if (FD_ISSET(fde->fd, &w_fds)) flags |= TEVENT_FD_WRITE;
512                         if (flags) {
513                                 fde->handler(std_ev->ev, fde, flags, fde->private_data);
514                                 break;
515                         }
516                 }
517         }
518
519         return 0;
520 }
521
522 /*
523   do a single event loop using the events defined in ev
524 */
525 static int std_event_loop_once(struct tevent_context *ev, const char *location)
526 {
527         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
528                                                            struct std_event_context);
529         struct timeval tval;
530
531         if (ev->signal_events &&
532             tevent_common_check_signal(ev)) {
533                 return 0;
534         }
535
536         if (ev->immediate_events &&
537             tevent_common_loop_immediate(ev)) {
538                 return 0;
539         }
540
541         tval = tevent_common_loop_timer_delay(ev);
542         if (tevent_timeval_is_zero(&tval)) {
543                 return 0;
544         }
545
546         epoll_check_reopen(std_ev);
547
548         if (epoll_event_loop(std_ev, &tval) == 0) {
549                 return 0;
550         }
551
552         return std_event_loop_select(std_ev, &tval);
553 }
554
555 static const struct tevent_ops std_event_ops = {
556         .context_init           = std_event_context_init,
557         .add_fd                 = std_event_add_fd,
558         .set_fd_close_fn        = tevent_common_fd_set_close_fn,
559         .get_fd_flags           = tevent_common_fd_get_flags,
560         .set_fd_flags           = std_event_set_fd_flags,
561         .add_timer              = tevent_common_add_timer,
562         .schedule_immediate     = tevent_common_schedule_immediate,
563         .add_signal             = tevent_common_add_signal,
564         .loop_once              = std_event_loop_once,
565         .loop_wait              = tevent_common_loop_wait,
566 };
567
568
569 _PRIVATE_ bool tevent_standard_init(void)
570 {
571         return tevent_register_backend("standard", &std_event_ops);
572 }