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