LCOV - code coverage report
Current view: top level - lib/tevent - tevent_poll.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 183 242 75.6 %
Date: 2021-09-23 10:06:22 Functions: 14 14 100.0 %

          Line data    Source code
       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          22 : 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          22 :         TALLOC_FREE(ev->additional_data);
      77             : 
      78          22 :         poll_ev = talloc_zero(ev, struct poll_event_context);
      79          22 :         if (poll_ev == NULL) {
      80           0 :                 return -1;
      81             :         }
      82          22 :         poll_ev->ev = ev;
      83          22 :         ev->additional_data = poll_ev;
      84          22 :         return 0;
      85             : }
      86             : 
      87           8 : static int poll_event_context_init_mt(struct tevent_context *ev)
      88             : {
      89             :         struct poll_event_context *poll_ev;
      90             :         int ret;
      91             : 
      92           8 :         ret = poll_event_context_init(ev);
      93           8 :         if (ret == -1) {
      94           0 :                 return ret;
      95             :         }
      96             : 
      97           8 :         poll_ev = talloc_get_type_abort(
      98             :                 ev->additional_data, struct poll_event_context);
      99             : 
     100           8 :         ret = tevent_common_wakeup_init(ev);
     101           8 :         if (ret != 0) {
     102           0 :                 return ret;
     103             :         }
     104             : 
     105           8 :         poll_ev->use_mt_mode = true;
     106             : 
     107           8 :         return 0;
     108             : }
     109             : 
     110         953 : static void poll_event_wake_pollthread(struct poll_event_context *poll_ev)
     111             : {
     112        1047 :         if (!poll_ev->use_mt_mode) {
     113           5 :                 return;
     114             :         }
     115         991 :         tevent_common_wakeup(poll_ev->ev);
     116             : }
     117             : 
     118             : /*
     119             :   destroy an fd_event
     120             : */
     121         609 : static int poll_event_fd_destructor(struct tevent_fd *fde)
     122             : {
     123         609 :         struct tevent_context *ev = fde->event_ctx;
     124             :         struct poll_event_context *poll_ev;
     125         609 :         uint64_t del_idx = fde->additional_flags;
     126             : 
     127         609 :         if (ev == NULL) {
     128         380 :                 goto done;
     129             :         }
     130             : 
     131         218 :         poll_ev = talloc_get_type_abort(
     132             :                 ev->additional_data, struct poll_event_context);
     133             : 
     134         218 :         if (del_idx == UINT64_MAX) {
     135           0 :                 goto done;
     136             :         }
     137             : 
     138         215 :         poll_ev->fdes[del_idx] = NULL;
     139         215 :         poll_ev->deleted = true;
     140         215 :         poll_event_wake_pollthread(poll_ev);
     141         623 : done:
     142         609 :         return tevent_common_fd_destructor(fde);
     143             : }
     144             : 
     145         566 : 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         566 :         struct poll_event_context *poll_ev = talloc_get_type_abort(
     153             :                 ev->additional_data, struct poll_event_context);
     154             : 
     155         566 :         tevent_common_schedule_immediate(im, ev, handler, private_data,
     156             :                                          handler_name, location);
     157         566 :         poll_event_wake_pollthread(poll_ev);
     158         566 : }
     159             : 
     160             : /*
     161             :   Private function called by "standard" backend fallback.
     162             :   Note this only allows fallback to "poll" backend, not "poll-mt".
     163             : */
     164         247 : _PRIVATE_ bool tevent_poll_event_add_fd_internal(struct tevent_context *ev,
     165             :                                                  struct tevent_fd *fde)
     166             : {
     167         247 :         struct poll_event_context *poll_ev = talloc_get_type_abort(
     168             :                 ev->additional_data, struct poll_event_context);
     169         247 :         uint64_t fde_idx = UINT64_MAX;
     170             :         size_t num_fdes;
     171             : 
     172         247 :         fde->additional_flags = UINT64_MAX;
     173         247 :         talloc_set_destructor(fde, poll_event_fd_destructor);
     174             : 
     175         247 :         if (fde->flags == 0) {
     176             :                 /*
     177             :                  * Nothing more to do...
     178             :                  */
     179           0 :                 return true;
     180             :         }
     181             : 
     182             :         /*
     183             :          * We need to add it to the end of the 'fdes' array.
     184             :          */
     185         242 :         num_fdes = poll_ev->num_fdes + 1;
     186         242 :         if (num_fdes > talloc_array_length(poll_ev->fdes)) {
     187          19 :                 struct tevent_fd **tmp_fdes = NULL;
     188             :                 size_t array_length;
     189             : 
     190          19 :                 array_length = (num_fdes + 15) & ~15; /* round up to 16 */
     191             : 
     192          19 :                 tmp_fdes = talloc_realloc(poll_ev,
     193             :                                           poll_ev->fdes,
     194             :                                           struct tevent_fd *,
     195             :                                           array_length);
     196          19 :                 if (tmp_fdes == NULL) {
     197           0 :                         return false;
     198             :                 }
     199          19 :                 poll_ev->fdes = tmp_fdes;
     200             :         }
     201             : 
     202         242 :         fde_idx = poll_ev->num_fdes;
     203         242 :         fde->additional_flags = fde_idx;
     204         242 :         poll_ev->fdes[fde_idx] = fde;
     205         242 :         poll_ev->num_fdes++;
     206             : 
     207         242 :         return true;
     208             : }
     209             : 
     210             : /*
     211             :   add a fd based event
     212             :   return NULL on failure (memory allocation error)
     213             : */
     214         228 : 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         228 :         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         228 :         if (fd < 0) {
     228           0 :                 return NULL;
     229             :         }
     230             : 
     231         228 :         fde = tevent_common_add_fd(ev,
     232             :                                    mem_ctx,
     233             :                                    fd,
     234             :                                    flags,
     235             :                                    handler,
     236             :                                    private_data,
     237             :                                    handler_name,
     238             :                                    location);
     239         228 :         if (fde == NULL) {
     240           0 :                 return NULL;
     241             :         }
     242             : 
     243         228 :         ok = tevent_poll_event_add_fd_internal(ev, fde);
     244         228 :         if (!ok) {
     245           0 :                 TALLOC_FREE(fde);
     246           0 :                 return NULL;
     247             :         }
     248         228 :         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         194 :         return fde;
     255             : }
     256             : 
     257             : /*
     258             :   set the fd event flags
     259             : */
     260          40 : static void poll_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
     261             : {
     262          40 :         struct tevent_context *ev = fde->event_ctx;
     263             :         struct poll_event_context *poll_ev;
     264          40 :         uint64_t idx = fde->additional_flags;
     265             :         uint16_t pollflags;
     266             : 
     267          40 :         if (ev == NULL) {
     268           0 :                 return;
     269             :         }
     270             : 
     271          40 :         if (fde->flags == flags) {
     272           2 :                 return;
     273             :         }
     274             : 
     275          38 :         poll_ev = talloc_get_type_abort(
     276             :                 ev->additional_data, struct poll_event_context);
     277             : 
     278          38 :         fde->flags = flags;
     279             : 
     280          38 :         if (idx == UINT64_MAX) {
     281             :                 /*
     282             :                  * We move it between the fresh and disabled lists.
     283             :                  */
     284          14 :                 tevent_poll_event_add_fd_internal(ev, fde);
     285          14 :                 poll_event_wake_pollthread(poll_ev);
     286           0 :                 return;
     287             :         }
     288             : 
     289          24 :         if (fde->flags == 0) {
     290             :                 /*
     291             :                  * We need to remove it from the array
     292             :                  * and move it to the disabled list.
     293             :                  */
     294          18 :                 poll_ev->fdes[idx] = NULL;
     295          18 :                 poll_ev->deleted = true;
     296          18 :                 fde->additional_flags = UINT64_MAX;
     297          18 :                 poll_event_wake_pollthread(poll_ev);
     298           0 :                 return;
     299             :         }
     300             : 
     301           6 :         if (idx >= poll_ev->num_fds) {
     302             :                 /*
     303             :                  * Not yet added to the
     304             :                  * poll_ev->fds array.
     305             :                  */
     306           2 :                 poll_event_wake_pollthread(poll_ev);
     307           0 :                 return;
     308             :         }
     309             : 
     310           4 :         pollflags = 0;
     311             : 
     312           4 :         if (flags & TEVENT_FD_READ) {
     313           4 :                 pollflags |= (POLLIN|POLLHUP);
     314             :         }
     315           4 :         if (flags & TEVENT_FD_WRITE) {
     316           0 :                 pollflags |= (POLLOUT);
     317             :         }
     318           4 :         poll_ev->fds[idx].events = pollflags;
     319             : 
     320           4 :         poll_event_wake_pollthread(poll_ev);
     321             : }
     322             : 
     323      422767 : 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      422767 :         if (poll_ev->deleted) {
     330             : 
     331         982 :                 for (i=0; i < poll_ev->num_fds;) {
     332         590 :                         struct tevent_fd *fde = poll_ev->fdes[i];
     333             :                         size_t ci;
     334             : 
     335         590 :                         if (fde != NULL) {
     336         386 :                                 i++;
     337         386 :                                 continue;
     338             :                         }
     339             : 
     340             :                         /*
     341             :                          * This fde was talloc_free()'ed. Delete it
     342             :                          * from the arrays
     343             :                          */
     344         204 :                         poll_ev->num_fds -= 1;
     345         204 :                         ci = poll_ev->num_fds;
     346         204 :                         if (ci > i) {
     347           0 :                                 poll_ev->fds[i] = poll_ev->fds[ci];
     348           0 :                                 poll_ev->fdes[i] = poll_ev->fdes[ci];
     349           0 :                                 if (poll_ev->fdes[i] != NULL) {
     350           0 :                                         poll_ev->fdes[i]->additional_flags = i;
     351             :                                 }
     352             :                         }
     353         204 :                         poll_ev->fds[ci] = (struct pollfd) { .fd = -1 };
     354         204 :                         poll_ev->fdes[ci] = NULL;
     355             :                 }
     356         204 :                 poll_ev->deleted = false;
     357             :         }
     358             : 
     359      422767 :         if (poll_ev->num_fds == poll_ev->num_fdes) {
     360         556 :                 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         229 :         if (poll_ev->num_fdes > talloc_array_length(poll_ev->fds)) {
     369          14 :                 struct pollfd *tmp_fds = NULL;
     370             : 
     371             :                 /*
     372             :                  * Make sure both allocated the same length.
     373             :                  */
     374          14 :                 array_length = talloc_array_length(poll_ev->fdes);
     375             : 
     376          14 :                 tmp_fds = talloc_realloc(poll_ev,
     377             :                                          poll_ev->fds,
     378             :                                          struct pollfd,
     379             :                                          array_length);
     380          14 :                 if (tmp_fds == NULL) {
     381           0 :                         return false;
     382             :                 }
     383          14 :                 poll_ev->fds = tmp_fds;
     384             :         }
     385             : 
     386             :         /*
     387             :          * Now setup the new elements.
     388             :          */
     389         668 :         for (i = poll_ev->num_fds; i < poll_ev->num_fdes; i++) {
     390         439 :                 struct tevent_fd *fde = poll_ev->fdes[i];
     391         439 :                 struct pollfd *pfd = &poll_ev->fds[poll_ev->num_fds];
     392             : 
     393         439 :                 if (fde == NULL) {
     394         204 :                         continue;
     395             :                 }
     396             : 
     397         235 :                 if (i > poll_ev->num_fds) {
     398         192 :                         poll_ev->fdes[poll_ev->num_fds] = fde;
     399         192 :                         fde->additional_flags = poll_ev->num_fds;
     400         192 :                         poll_ev->fdes[i] = NULL;
     401             :                 }
     402             : 
     403         235 :                 pfd->fd = fde->fd;
     404         235 :                 pfd->events = 0;
     405         235 :                 pfd->revents = 0;
     406             : 
     407         235 :                 if (fde->flags & TEVENT_FD_READ) {
     408         223 :                         pfd->events |= (POLLIN|POLLHUP);
     409             :                 }
     410         235 :                 if (fde->flags & TEVENT_FD_WRITE) {
     411          20 :                         pfd->events |= (POLLOUT);
     412             :                 }
     413             : 
     414         235 :                 poll_ev->num_fds += 1;
     415             :         }
     416             :         /* Both are in sync again */
     417         229 :         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         229 :         array_length = (poll_ev->num_fds + 15) & ~15; /* round up to 16 */
     425         229 :         array_length = MAX(array_length, 16);
     426         229 :         if (array_length < talloc_array_length(poll_ev->fdes)) {
     427           0 :                 struct tevent_fd **tmp_fdes = NULL;
     428           0 :                 struct pollfd *tmp_fds = NULL;
     429             : 
     430           0 :                 tmp_fdes = talloc_realloc(poll_ev,
     431             :                                           poll_ev->fdes,
     432             :                                           struct tevent_fd *,
     433             :                                           array_length);
     434           0 :                 if (tmp_fdes == NULL) {
     435           0 :                         return false;
     436             :                 }
     437           0 :                 poll_ev->fdes = tmp_fdes;
     438             : 
     439           0 :                 tmp_fds = talloc_realloc(poll_ev,
     440             :                                          poll_ev->fds,
     441             :                                          struct pollfd,
     442             :                                          array_length);
     443           0 :                 if (tmp_fds == NULL) {
     444           0 :                         return false;
     445             :                 }
     446           0 :                 poll_ev->fds = tmp_fds;
     447             :         }
     448             : 
     449         194 :         return true;
     450             : }
     451             : 
     452             : /*
     453             :   event loop handling using poll()
     454             : */
     455      422767 : static int poll_event_loop_poll(struct tevent_context *ev,
     456             :                                 struct timeval *tvalp)
     457             : {
     458      422767 :         struct poll_event_context *poll_ev = talloc_get_type_abort(
     459             :                 ev->additional_data, struct poll_event_context);
     460             :         int pollrtn;
     461      422767 :         int timeout = -1;
     462             :         int poll_errno;
     463      422767 :         struct tevent_fd *fde = NULL;
     464      422767 :         struct tevent_fd *next = NULL;
     465             :         unsigned i;
     466             :         bool ok;
     467             : 
     468      422767 :         if (ev->signal_events && tevent_common_check_signal(ev)) {
     469           0 :                 return 0;
     470             :         }
     471             : 
     472      422767 :         if (tvalp != NULL) {
     473      422767 :                 timeout = tvalp->tv_sec * 1000;
     474      422767 :                 timeout += (tvalp->tv_usec + 999) / 1000;
     475             :         }
     476             : 
     477      422767 :         ok = poll_event_sync_arrays(ev, poll_ev);
     478      422767 :         if (!ok) {
     479           0 :                 return -1;
     480             :         }
     481             : 
     482      422767 :         tevent_trace_point_callback(poll_ev->ev, TEVENT_TRACE_BEFORE_WAIT);
     483      844784 :         pollrtn = poll(poll_ev->fds, poll_ev->num_fds, timeout);
     484      422767 :         poll_errno = errno;
     485      422767 :         tevent_trace_point_callback(poll_ev->ev, TEVENT_TRACE_AFTER_WAIT);
     486             : 
     487      422767 :         if (pollrtn == -1 && poll_errno == EINTR && ev->signal_events) {
     488           0 :                 tevent_common_check_signal(ev);
     489           0 :                 return 0;
     490             :         }
     491             : 
     492      422767 :         if (pollrtn == 0 && tvalp) {
     493             :                 /* we don't care about a possible delay here */
     494           8 :                 tevent_common_loop_timer_delay(ev);
     495           8 :                 return 0;
     496             :         }
     497             : 
     498      422759 :         if (pollrtn <= 0) {
     499             :                 /*
     500             :                  * No fd's ready
     501             :                  */
     502           0 :                 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     1688928 :         for (fde = ev->fd_events; fde; fde = next) {
     510     1266919 :                 uint64_t idx = fde->additional_flags;
     511             :                 struct pollfd *pfd;
     512     1266919 :                 uint16_t flags = 0;
     513             : 
     514     1266919 :                 next = fde->next;
     515             : 
     516     1266919 :                 if (idx == UINT64_MAX) {
     517          18 :                         continue;
     518             :                 }
     519             : 
     520     1266901 :                 pfd = &poll_ev->fds[idx];
     521             : 
     522     1266901 :                 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           0 :                         tevent_debug(ev, TEVENT_DEBUG_ERROR,
     533             :                                      "POLLNVAL on fde[%p] fd[%d] - disabling\n",
     534             :                                      fde, pfd->fd);
     535           0 :                         poll_ev->fdes[idx] = NULL;
     536           0 :                         poll_ev->deleted = true;
     537           0 :                         DLIST_REMOVE(ev->fd_events, fde);
     538           0 :                         fde->wrapper = NULL;
     539           0 :                         fde->event_ctx = NULL;
     540           0 :                         continue;
     541             :                 }
     542             : 
     543     1266901 :                 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           8 :                         if (!(fde->flags & TEVENT_FD_READ)) {
     550           0 :                                 TEVENT_FD_NOT_WRITEABLE(fde);
     551           0 :                                 continue;
     552             :                         }
     553           0 :                         flags |= TEVENT_FD_READ;
     554             :                 }
     555     1266901 :                 if (pfd->revents & POLLIN) {
     556      282280 :                         flags |= TEVENT_FD_READ;
     557             :                 }
     558     1266901 :                 if (pfd->revents & POLLOUT) {
     559      141041 :                         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     1266901 :                 flags &= fde->flags;
     567     1266901 :                 if (flags != 0) {
     568      422759 :                         DLIST_DEMOTE(ev->fd_events, fde);
     569      422759 :                         return tevent_common_invoke_fd_handler(fde, flags, NULL);
     570             :                 }
     571             :         }
     572             : 
     573           0 :         for (i = 0; i < poll_ev->num_fds; i++) {
     574           0 :                 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           0 :                         fde = poll_ev->fdes[i];
     583           0 :                         tevent_debug(ev, TEVENT_DEBUG_WARNING,
     584             :                                      "POLLNVAL on dangling fd[%d] fde[%p] - disabling\n",
     585           0 :                                      poll_ev->fds[i].fd, fde);
     586           0 :                         poll_ev->fdes[i] = NULL;
     587           0 :                         poll_ev->deleted = true;
     588           0 :                         if (fde != NULL) {
     589           0 :                                 DLIST_REMOVE(ev->fd_events, fde);
     590           0 :                                 fde->wrapper = NULL;
     591           0 :                                 fde->event_ctx = NULL;
     592             :                         }
     593             :                 }
     594             :         }
     595             : 
     596           0 :         return 0;
     597             : }
     598             : 
     599             : /*
     600             :   do a single event loop using the events defined in ev
     601             : */
     602      563626 : static int poll_event_loop_once(struct tevent_context *ev,
     603             :                                 const char *location)
     604             : {
     605             :         struct timeval tval;
     606             : 
     607     1125515 :         if (ev->signal_events &&
     608      561889 :             tevent_common_check_signal(ev)) {
     609           0 :                 return 0;
     610             :         }
     611             : 
     612      423151 :         if (ev->threaded_contexts != NULL) {
     613           2 :                 tevent_common_threaded_activate_immediate(ev);
     614             :         }
     615             : 
     616      423531 :         if (ev->immediate_events &&
     617         380 :             tevent_common_loop_immediate(ev)) {
     618         377 :                 return 0;
     619             :         }
     620             : 
     621      422771 :         tval = tevent_common_loop_timer_delay(ev);
     622      422771 :         if (tevent_timeval_is_zero(&tval)) {
     623           0 :                 return 0;
     624             :         }
     625             : 
     626      422767 :         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       65046 : _PRIVATE_ bool tevent_poll_init(void)
     643             : {
     644       65046 :         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       65046 : _PRIVATE_ bool tevent_poll_mt_init(void)
     661             : {
     662       65046 :         return tevent_register_backend("poll_mt", &poll_event_mt_ops);
     663             : }

Generated by: LCOV version 1.13