68885e94c0feb09f8c37e00dc096155ea95e0656
[metze/samba/wip.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, next_i;
447         int poll_errno;
448
449         if (ev->signal_events && tevent_common_check_signal(ev)) {
450                 return 0;
451         }
452
453         if (tvalp != NULL) {
454                 timeout = tvalp->tv_sec * 1000;
455                 timeout += (tvalp->tv_usec + 999) / 1000;
456         }
457
458         poll_event_drain_signal_fd(poll_ev);
459
460         if (!poll_event_setup_fresh(ev, poll_ev)) {
461                 return -1;
462         }
463
464         tevent_trace_point_callback(poll_ev->ev, TEVENT_TRACE_BEFORE_WAIT);
465         pollrtn = poll(poll_ev->fds, poll_ev->num_fds, timeout);
466         poll_errno = errno;
467         tevent_trace_point_callback(poll_ev->ev, TEVENT_TRACE_AFTER_WAIT);
468
469         if (pollrtn == -1 && poll_errno == EINTR && ev->signal_events) {
470                 tevent_common_check_signal(ev);
471                 return 0;
472         }
473
474         if (pollrtn == 0 && tvalp) {
475                 /* we don't care about a possible delay here */
476                 tevent_common_loop_timer_delay(ev);
477                 return 0;
478         }
479
480         if (pollrtn <= 0) {
481                 /*
482                  * No fd's ready
483                  */
484                 return 0;
485         }
486
487         first_fd = (poll_ev->signal_fd != -1) ? 1 : 0;
488
489         /* at least one file descriptor is ready - check
490            which ones and call the handler, being careful to allow
491            the handler to remove itself when called */
492
493         for (i=first_fd; i<poll_ev->num_fds; i = next_i) {
494                 struct pollfd *pfd;
495                 struct tevent_fd *fde;
496                 uint16_t flags = 0;
497
498                 next_i = i + 1;
499
500                 fde = poll_ev->fdes[i];
501                 if (fde == NULL) {
502                         /*
503                          * This fde was talloc_free()'ed. Delete it
504                          * from the arrays
505                          */
506                         poll_ev->num_fds -= 1;
507                         if (poll_ev->num_fds == i) {
508                                 break;
509                         }
510                         poll_ev->fds[i] = poll_ev->fds[poll_ev->num_fds];
511                         poll_ev->fdes[i] = poll_ev->fdes[poll_ev->num_fds];
512                         if (poll_ev->fdes[i] != NULL) {
513                                 poll_ev->fdes[i]->additional_flags = i;
514                         }
515                         /* we have to reprocess position 'i' */
516                         next_i = i;
517                         continue;
518                 }
519
520                 pfd = &poll_ev->fds[i];
521
522                 if (pfd->revents & (POLLHUP|POLLERR)) {
523                         /* If we only wait for TEVENT_FD_WRITE, we
524                            should not tell the event handler about it,
525                            and remove the writable flag, as we only
526                            report errors when waiting for read events
527                            to match the select behavior. */
528                         if (!(fde->flags & TEVENT_FD_READ)) {
529                                 TEVENT_FD_NOT_WRITEABLE(fde);
530                                 continue;
531                         }
532                         flags |= TEVENT_FD_READ;
533                 }
534                 if (pfd->revents & POLLIN) {
535                         flags |= TEVENT_FD_READ;
536                 }
537                 if (pfd->revents & POLLOUT) {
538                         flags |= TEVENT_FD_WRITE;
539                 }
540                 if (flags != 0) {
541                         fde->handler(ev, fde, flags, fde->private_data);
542                         break;
543                 }
544         }
545
546         return 0;
547 }
548
549 /*
550   do a single event loop using the events defined in ev
551 */
552 static int poll_event_loop_once(struct tevent_context *ev,
553                                 const char *location)
554 {
555         struct timeval tval;
556
557         if (ev->signal_events &&
558             tevent_common_check_signal(ev)) {
559                 return 0;
560         }
561
562         if (ev->immediate_events &&
563             tevent_common_loop_immediate(ev)) {
564                 return 0;
565         }
566
567         tval = tevent_common_loop_timer_delay(ev);
568         if (tevent_timeval_is_zero(&tval)) {
569                 return 0;
570         }
571
572         return poll_event_loop_poll(ev, &tval);
573 }
574
575 static int poll_event_loop_wait(struct tevent_context *ev,
576                                 const char *location)
577 {
578         struct poll_event_context *poll_ev = talloc_get_type_abort(
579                 ev->additional_data, struct poll_event_context);
580
581         /*
582          * loop as long as we have events pending
583          */
584         while (ev->fd_events ||
585                ev->timer_events ||
586                ev->immediate_events ||
587                ev->signal_events ||
588                poll_ev->fresh) {
589                 int ret;
590                 ret = _tevent_loop_once(ev, location);
591                 if (ret != 0) {
592                         tevent_debug(ev, TEVENT_DEBUG_FATAL,
593                                      "_tevent_loop_once() failed: %d - %s\n",
594                                      ret, strerror(errno));
595                         return ret;
596                 }
597         }
598
599         tevent_debug(ev, TEVENT_DEBUG_WARNING,
600                      "poll_event_loop_wait() out of events\n");
601         return 0;
602 }
603
604 static const struct tevent_ops poll_event_ops = {
605         .context_init           = poll_event_context_init,
606         .add_fd                 = poll_event_add_fd,
607         .set_fd_close_fn        = tevent_common_fd_set_close_fn,
608         .get_fd_flags           = tevent_common_fd_get_flags,
609         .set_fd_flags           = poll_event_set_fd_flags,
610         .add_timer              = tevent_common_add_timer,
611         .schedule_immediate     = tevent_common_schedule_immediate,
612         .add_signal             = tevent_common_add_signal,
613         .loop_once              = poll_event_loop_once,
614         .loop_wait              = poll_event_loop_wait,
615 };
616
617 _PRIVATE_ bool tevent_poll_init(void)
618 {
619         return tevent_register_backend("poll", &poll_event_ops);
620 }
621
622 static const struct tevent_ops poll_event_mt_ops = {
623         .context_init           = poll_event_context_init_mt,
624         .add_fd                 = poll_event_add_fd,
625         .set_fd_close_fn        = tevent_common_fd_set_close_fn,
626         .get_fd_flags           = tevent_common_fd_get_flags,
627         .set_fd_flags           = poll_event_set_fd_flags,
628         .add_timer              = tevent_common_add_timer,
629         .schedule_immediate     = poll_event_schedule_immediate,
630         .add_signal             = tevent_common_add_signal,
631         .loop_once              = poll_event_loop_once,
632         .loop_wait              = poll_event_loop_wait,
633 };
634
635 _PRIVATE_ bool tevent_poll_mt_init(void)
636 {
637         return tevent_register_backend("poll_mt", &poll_event_mt_ops);
638 }