tevent: Add a private function tevent_poll_event_add_fd_internal().
[samba.git] / lib / tevent / tevent_poll.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 #include "replace.h"
26 #include "system/filesys.h"
27 #include "system/select.h"
28 #include "tevent.h"
29 #include "tevent_util.h"
30 #include "tevent_internal.h"
31
32 struct poll_event_context {
33         /* a pointer back to the generic event_context */
34         struct tevent_context *ev;
35
36         /*
37          * A DLIST for fresh fde's added by poll_event_add_fd but not
38          * picked up yet by poll_event_loop_once
39          */
40         struct tevent_fd *fresh;
41
42         /*
43          * These two arrays are maintained together.
44          */
45         struct pollfd *fds;
46         struct tevent_fd **fdes;
47         unsigned num_fds;
48
49         /*
50          * Signal fd to wake the poll() thread
51          */
52         int signal_fd;
53
54         /* information for exiting from the event loop */
55         int exit_code;
56 };
57
58 static int poll_event_context_destructor(struct poll_event_context *poll_ev)
59 {
60         struct tevent_fd *fd, *fn;
61
62         for (fd = poll_ev->fresh; fd; fd = fn) {
63                 fn = fd->next;
64                 fd->event_ctx = NULL;
65                 DLIST_REMOVE(poll_ev->fresh, fd);
66         }
67
68         if (poll_ev->signal_fd == -1) {
69                 /*
70                  * Non-threaded, no signal pipe
71                  */
72                 return 0;
73         }
74
75         close(poll_ev->signal_fd);
76         poll_ev->signal_fd = -1;
77
78         if (poll_ev->num_fds == 0) {
79                 return 0;
80         }
81         if (poll_ev->fds[0].fd != -1) {
82                 close(poll_ev->fds[0].fd);
83                 poll_ev->fds[0].fd = -1;
84         }
85         return 0;
86 }
87
88 /*
89   create a poll_event_context structure.
90 */
91 static int poll_event_context_init(struct tevent_context *ev)
92 {
93         struct poll_event_context *poll_ev;
94
95         /*
96          * we might be called during tevent_re_initialise()
97          * which means we need to free our old additional_data
98          * in order to detach old fd events from the
99          * poll_ev->fresh list
100          */
101         TALLOC_FREE(ev->additional_data);
102
103         poll_ev = talloc_zero(ev, struct poll_event_context);
104         if (poll_ev == NULL) {
105                 return -1;
106         }
107         poll_ev->ev = ev;
108         poll_ev->signal_fd = -1;
109         ev->additional_data = poll_ev;
110         talloc_set_destructor(poll_ev, poll_event_context_destructor);
111         return 0;
112 }
113
114 static bool set_nonblock(int fd)
115 {
116         int val;
117
118         val = fcntl(fd, F_GETFL, 0);
119         if (val == -1) {
120                 return false;
121         }
122         val |= O_NONBLOCK;
123
124         return (fcntl(fd, F_SETFL, val) != -1);
125 }
126
127 static int poll_event_context_init_mt(struct tevent_context *ev)
128 {
129         struct poll_event_context *poll_ev;
130         struct pollfd *pfd;
131         int fds[2];
132         int ret;
133
134         ret = poll_event_context_init(ev);
135         if (ret == -1) {
136                 return ret;
137         }
138
139         poll_ev = talloc_get_type_abort(
140                 ev->additional_data, struct poll_event_context);
141
142         poll_ev->fds = talloc_zero(poll_ev, struct pollfd);
143         if (poll_ev->fds == NULL) {
144                 return -1;
145         }
146
147         ret = pipe(fds);
148         if (ret == -1) {
149                 return -1;
150         }
151
152         if (!set_nonblock(fds[0]) || !set_nonblock(fds[1])) {
153                 close(fds[0]);
154                 close(fds[1]);
155                 return -1;
156         }
157
158         poll_ev->signal_fd = fds[1];
159
160         pfd = &poll_ev->fds[0];
161         pfd->fd = fds[0];
162         pfd->events = (POLLIN|POLLHUP);
163
164         poll_ev->num_fds = 1;
165
166         talloc_set_destructor(poll_ev, poll_event_context_destructor);
167
168         return 0;
169 }
170
171 static void poll_event_wake_pollthread(struct poll_event_context *poll_ev)
172 {
173         char c;
174         ssize_t ret;
175
176         if (poll_ev->signal_fd == -1) {
177                 return;
178         }
179         c = 0;
180         do {
181                 ret = write(poll_ev->signal_fd, &c, sizeof(c));
182         } while ((ret == -1) && (errno == EINTR));
183 }
184
185 static void poll_event_drain_signal_fd(struct poll_event_context *poll_ev)
186 {
187         char buf[16];
188         ssize_t ret;
189         int fd;
190
191         if (poll_ev->signal_fd == -1) {
192                 return;
193         }
194
195         if (poll_ev->num_fds < 1) {
196                 return;
197         }
198         fd = poll_ev->fds[0].fd;
199
200         do {
201                 ret = read(fd, buf, sizeof(buf));
202         } while (ret == sizeof(buf));
203 }
204
205 /*
206   destroy an fd_event
207 */
208 static int poll_event_fd_destructor(struct tevent_fd *fde)
209 {
210         struct tevent_context *ev = fde->event_ctx;
211         struct poll_event_context *poll_ev;
212         uint64_t del_idx = fde->additional_flags;
213
214         if (ev == NULL) {
215                 goto done;
216         }
217
218         poll_ev = talloc_get_type_abort(
219                 ev->additional_data, struct poll_event_context);
220
221         poll_ev->fdes[del_idx] = NULL;
222         poll_event_wake_pollthread(poll_ev);
223 done:
224         return tevent_common_fd_destructor(fde);
225 }
226
227 static int poll_fresh_fde_destructor(struct tevent_fd *fde)
228 {
229         struct tevent_context *ev = fde->event_ctx;
230         struct poll_event_context *poll_ev;
231
232         if (ev == NULL) {
233                 goto done;
234         }
235         poll_ev = talloc_get_type_abort(
236                 ev->additional_data, struct poll_event_context);
237
238         DLIST_REMOVE(poll_ev->fresh, fde);
239 done:
240         return tevent_common_fd_destructor(fde);
241 }
242
243 static void poll_event_schedule_immediate(struct tevent_immediate *im,
244                                           struct tevent_context *ev,
245                                           tevent_immediate_handler_t handler,
246                                           void *private_data,
247                                           const char *handler_name,
248                                           const char *location)
249 {
250         struct poll_event_context *poll_ev = talloc_get_type_abort(
251                 ev->additional_data, struct poll_event_context);
252
253         tevent_common_schedule_immediate(im, ev, handler, private_data,
254                                          handler_name, location);
255         poll_event_wake_pollthread(poll_ev);
256 }
257
258 /*
259   Private function called by "standard" backend fallback.
260   Note this only allows fallback to "poll" backend, not "poll-mt".
261 */
262 _PRIVATE_ void tevent_poll_event_add_fd_internal(struct tevent_context *ev,
263                                                  struct tevent_fd *fde)
264 {
265         struct poll_event_context *poll_ev = talloc_get_type_abort(
266                 ev->additional_data, struct poll_event_context);
267
268         fde->additional_flags   = UINT64_MAX;
269         fde->additional_data    = NULL;
270         DLIST_ADD(poll_ev->fresh, fde);
271         talloc_set_destructor(fde, poll_fresh_fde_destructor);
272 }
273
274 /*
275   add a fd based event
276   return NULL on failure (memory allocation error)
277 */
278 static struct tevent_fd *poll_event_add_fd(struct tevent_context *ev,
279                                            TALLOC_CTX *mem_ctx,
280                                            int fd, uint16_t flags,
281                                            tevent_fd_handler_t handler,
282                                            void *private_data,
283                                            const char *handler_name,
284                                            const char *location)
285 {
286         struct poll_event_context *poll_ev = talloc_get_type_abort(
287                 ev->additional_data, struct poll_event_context);
288         struct tevent_fd *fde;
289
290         if (fd < 0) {
291                 return NULL;
292         }
293
294         fde = talloc(mem_ctx ? mem_ctx : ev, struct tevent_fd);
295         if (fde == NULL) {
296                 return NULL;
297         }
298         fde->event_ctx          = ev;
299         fde->fd                 = fd;
300         fde->flags              = flags;
301         fde->handler            = handler;
302         fde->close_fn           = NULL;
303         fde->private_data       = private_data;
304         fde->handler_name       = handler_name;
305         fde->location           = location;
306         fde->additional_flags   = UINT64_MAX;
307         fde->additional_data    = NULL;
308
309         DLIST_ADD(poll_ev->fresh, fde);
310         talloc_set_destructor(fde, poll_fresh_fde_destructor);
311         poll_event_wake_pollthread(poll_ev);
312
313         /*
314          * poll_event_loop_poll will take care of the rest in
315          * poll_event_setup_fresh
316          */
317         return fde;
318 }
319
320 /*
321   set the fd event flags
322 */
323 static void poll_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
324 {
325         struct tevent_context *ev = fde->event_ctx;
326         struct poll_event_context *poll_ev;
327         uint64_t idx = fde->additional_flags;
328         uint16_t pollflags;
329
330         if (ev == NULL) {
331                 return;
332         }
333         poll_ev = talloc_get_type_abort(
334                 ev->additional_data, struct poll_event_context);
335
336         fde->flags = flags;
337
338         if (idx == UINT64_MAX) {
339                 /*
340                  * poll_event_setup_fresh not yet called after this fde was
341                  * added. We don't have to do anything to transfer the changed
342                  * flags to the array passed to poll(2)
343                  */
344                 return;
345         }
346
347         pollflags = 0;
348
349         if (flags & TEVENT_FD_READ) {
350                 pollflags |= (POLLIN|POLLHUP);
351         }
352         if (flags & TEVENT_FD_WRITE) {
353                 pollflags |= (POLLOUT);
354         }
355         poll_ev->fds[idx].events = pollflags;
356
357         poll_event_wake_pollthread(poll_ev);
358 }
359
360 static bool poll_event_setup_fresh(struct tevent_context *ev,
361                                    struct poll_event_context *poll_ev)
362 {
363         struct tevent_fd *fde, *next;
364         unsigned num_fresh, num_fds;
365
366         if (poll_ev->fresh == NULL) {
367                 return true;
368         }
369
370         num_fresh = 0;
371         for (fde = poll_ev->fresh; fde; fde = fde->next) {
372                 num_fresh += 1;
373         }
374         num_fds = poll_ev->num_fds + num_fresh;
375
376         /*
377          * We check the length of fdes here. It is the last one
378          * enlarged, so if the realloc for poll_fd->fdes fails,
379          * poll_fd->fds will have at least the size of poll_fd->fdes
380          */
381
382         if (num_fds >= talloc_array_length(poll_ev->fdes)) {
383                 struct pollfd *tmp_fds;
384                 struct tevent_fd **tmp_fdes;
385                 unsigned array_length;
386
387                 array_length = (num_fds + 15) & ~15; /* round up to 16 */
388
389                 tmp_fds = talloc_realloc(
390                         poll_ev, poll_ev->fds, struct pollfd, array_length);
391                 if (tmp_fds == NULL) {
392                         return false;
393                 }
394                 poll_ev->fds = tmp_fds;
395
396                 tmp_fdes = talloc_realloc(
397                         poll_ev, poll_ev->fdes, struct tevent_fd *,
398                         array_length);
399                 if (tmp_fdes == NULL) {
400                         return false;
401                 }
402                 poll_ev->fdes = tmp_fdes;
403         }
404
405         for (fde = poll_ev->fresh; fde; fde = next) {
406                 struct pollfd *pfd;
407
408                 pfd = &poll_ev->fds[poll_ev->num_fds];
409
410                 pfd->fd = fde->fd;
411                 pfd->events = 0;
412                 pfd->revents = 0;
413
414                 if (fde->flags & TEVENT_FD_READ) {
415                         pfd->events |= (POLLIN|POLLHUP);
416                 }
417                 if (fde->flags & TEVENT_FD_WRITE) {
418                         pfd->events |= (POLLOUT);
419                 }
420
421                 fde->additional_flags = poll_ev->num_fds;
422                 poll_ev->fdes[poll_ev->num_fds] = fde;
423
424                 next = fde->next;
425                 DLIST_REMOVE(poll_ev->fresh, fde);
426                 DLIST_ADD(ev->fd_events, fde);
427
428                 talloc_set_destructor(fde, poll_event_fd_destructor);
429
430                 poll_ev->num_fds += 1;
431         }
432         return true;
433 }
434
435 /*
436   event loop handling using poll()
437 */
438 static int poll_event_loop_poll(struct tevent_context *ev,
439                                 struct timeval *tvalp)
440 {
441         struct poll_event_context *poll_ev = talloc_get_type_abort(
442                 ev->additional_data, struct poll_event_context);
443         int pollrtn;
444         int timeout = -1;
445         unsigned first_fd;
446         unsigned i;
447
448         if (ev->signal_events && tevent_common_check_signal(ev)) {
449                 return 0;
450         }
451
452         if (tvalp != NULL) {
453                 timeout = tvalp->tv_sec * 1000;
454                 timeout += (tvalp->tv_usec + 999) / 1000;
455         }
456
457         poll_event_drain_signal_fd(poll_ev);
458
459         if (!poll_event_setup_fresh(ev, poll_ev)) {
460                 return -1;
461         }
462
463         tevent_trace_point_callback(poll_ev->ev, TEVENT_TRACE_BEFORE_WAIT);
464         pollrtn = poll(poll_ev->fds, poll_ev->num_fds, timeout);
465         tevent_trace_point_callback(poll_ev->ev, TEVENT_TRACE_AFTER_WAIT);
466
467         if (pollrtn == -1 && errno == EINTR && ev->signal_events) {
468                 tevent_common_check_signal(ev);
469                 return 0;
470         }
471
472         if (pollrtn == 0 && tvalp) {
473                 /* we don't care about a possible delay here */
474                 tevent_common_loop_timer_delay(ev);
475                 return 0;
476         }
477
478         if (pollrtn <= 0) {
479                 /*
480                  * No fd's ready
481                  */
482                 return 0;
483         }
484
485         first_fd = (poll_ev->signal_fd != -1) ? 1 : 0;
486
487         /* at least one file descriptor is ready - check
488            which ones and call the handler, being careful to allow
489            the handler to remove itself when called */
490
491         for (i=first_fd; i<poll_ev->num_fds; i++) {
492                 struct pollfd *pfd;
493                 struct tevent_fd *fde;
494                 uint16_t flags = 0;
495
496                 fde = poll_ev->fdes[i];
497                 if (fde == NULL) {
498                         /*
499                          * This fde was talloc_free()'ed. Delete it
500                          * from the arrays
501                          */
502                         poll_ev->num_fds -= 1;
503                         poll_ev->fds[i] = poll_ev->fds[poll_ev->num_fds];
504                         poll_ev->fdes[i] = poll_ev->fdes[poll_ev->num_fds];
505                         if (poll_ev->fdes[i] != NULL) {
506                                 poll_ev->fdes[i]->additional_flags = i;
507                         }
508                         continue;
509                 }
510
511                 pfd = &poll_ev->fds[i];
512
513                 if (pfd->revents & (POLLHUP|POLLERR)) {
514                         /* If we only wait for TEVENT_FD_WRITE, we
515                            should not tell the event handler about it,
516                            and remove the writable flag, as we only
517                            report errors when waiting for read events
518                            to match the select behavior. */
519                         if (!(fde->flags & TEVENT_FD_READ)) {
520                                 TEVENT_FD_NOT_WRITEABLE(fde);
521                                 continue;
522                         }
523                         flags |= TEVENT_FD_READ;
524                 }
525                 if (pfd->revents & POLLIN) {
526                         flags |= TEVENT_FD_READ;
527                 }
528                 if (pfd->revents & POLLOUT) {
529                         flags |= TEVENT_FD_WRITE;
530                 }
531                 if (flags != 0) {
532                         fde->handler(ev, fde, flags, fde->private_data);
533                         break;
534                 }
535         }
536
537         return 0;
538 }
539
540 /*
541   do a single event loop using the events defined in ev
542 */
543 static int poll_event_loop_once(struct tevent_context *ev,
544                                 const char *location)
545 {
546         struct timeval tval;
547
548         if (ev->signal_events &&
549             tevent_common_check_signal(ev)) {
550                 return 0;
551         }
552
553         if (ev->immediate_events &&
554             tevent_common_loop_immediate(ev)) {
555                 return 0;
556         }
557
558         tval = tevent_common_loop_timer_delay(ev);
559         if (tevent_timeval_is_zero(&tval)) {
560                 return 0;
561         }
562
563         return poll_event_loop_poll(ev, &tval);
564 }
565
566 static int poll_event_loop_wait(struct tevent_context *ev,
567                                 const char *location)
568 {
569         struct poll_event_context *poll_ev = talloc_get_type_abort(
570                 ev->additional_data, struct poll_event_context);
571
572         /*
573          * loop as long as we have events pending
574          */
575         while (ev->fd_events ||
576                ev->timer_events ||
577                ev->immediate_events ||
578                ev->signal_events ||
579                poll_ev->fresh) {
580                 int ret;
581                 ret = _tevent_loop_once(ev, location);
582                 if (ret != 0) {
583                         tevent_debug(ev, TEVENT_DEBUG_FATAL,
584                                      "_tevent_loop_once() failed: %d - %s\n",
585                                      ret, strerror(errno));
586                         return ret;
587                 }
588         }
589
590         tevent_debug(ev, TEVENT_DEBUG_WARNING,
591                      "poll_event_loop_wait() out of events\n");
592         return 0;
593 }
594
595 static const struct tevent_ops poll_event_ops = {
596         .context_init           = poll_event_context_init,
597         .add_fd                 = poll_event_add_fd,
598         .set_fd_close_fn        = tevent_common_fd_set_close_fn,
599         .get_fd_flags           = tevent_common_fd_get_flags,
600         .set_fd_flags           = poll_event_set_fd_flags,
601         .add_timer              = tevent_common_add_timer,
602         .schedule_immediate     = tevent_common_schedule_immediate,
603         .add_signal             = tevent_common_add_signal,
604         .loop_once              = poll_event_loop_once,
605         .loop_wait              = poll_event_loop_wait,
606 };
607
608 _PRIVATE_ bool tevent_poll_init(void)
609 {
610         return tevent_register_backend("poll", &poll_event_ops);
611 }
612
613 static const struct tevent_ops poll_event_mt_ops = {
614         .context_init           = poll_event_context_init_mt,
615         .add_fd                 = poll_event_add_fd,
616         .set_fd_close_fn        = tevent_common_fd_set_close_fn,
617         .get_fd_flags           = tevent_common_fd_get_flags,
618         .set_fd_flags           = poll_event_set_fd_flags,
619         .add_timer              = tevent_common_add_timer,
620         .schedule_immediate     = poll_event_schedule_immediate,
621         .add_signal             = tevent_common_add_signal,
622         .loop_once              = poll_event_loop_once,
623         .loop_wait              = poll_event_loop_wait,
624 };
625
626 _PRIVATE_ bool tevent_poll_mt_init(void)
627 {
628         return tevent_register_backend("poll_mt", &poll_event_mt_ops);
629 }