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