LCOV - code coverage report
Current view: top level - lib/tevent - tevent_poll.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 226 261 86.6 %
Date: 2024-04-21 15:09:00 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          31 : static int poll_event_context_init(struct tevent_context *ev)
      67             : {
      68          22 :         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          31 :         TALLOC_FREE(ev->additional_data);
      77             : 
      78          31 :         poll_ev = talloc_zero(ev, struct poll_event_context);
      79          31 :         if (poll_ev == NULL) {
      80           0 :                 return -1;
      81             :         }
      82          31 :         poll_ev->ev = ev;
      83          31 :         ev->additional_data = poll_ev;
      84          31 :         return 0;
      85             : }
      86             : 
      87          13 : static int poll_event_context_init_mt(struct tevent_context *ev)
      88             : {
      89          11 :         struct poll_event_context *poll_ev;
      90          11 :         int ret;
      91             : 
      92          13 :         ret = poll_event_context_init(ev);
      93          13 :         if (ret == -1) {
      94           0 :                 return ret;
      95             :         }
      96             : 
      97          13 :         poll_ev = talloc_get_type_abort(
      98             :                 ev->additional_data, struct poll_event_context);
      99             : 
     100          13 :         ret = tevent_common_wakeup_init(ev);
     101          13 :         if (ret != 0) {
     102           0 :                 return ret;
     103             :         }
     104             : 
     105          13 :         poll_ev->use_mt_mode = true;
     106             : 
     107          13 :         return 0;
     108             : }
     109             : 
     110        1361 : static void poll_event_wake_pollthread(struct poll_event_context *poll_ev)
     111             : {
     112        1361 :         if (!poll_ev->use_mt_mode) {
     113           5 :                 return;
     114             :         }
     115        1148 :         tevent_common_wakeup(poll_ev->ev);
     116             : }
     117             : 
     118             : /*
     119             :   destroy an fd_event
     120             : */
     121         673 : static int poll_event_fd_destructor(struct tevent_fd *fde)
     122             : {
     123         673 :         struct tevent_context *ev = fde->event_ctx;
     124          98 :         struct poll_event_context *poll_ev;
     125         673 :         uint64_t del_idx = fde->additional_flags;
     126             : 
     127         673 :         if (ev == NULL) {
     128         437 :                 goto done;
     129             :         }
     130             : 
     131         236 :         poll_ev = talloc_get_type_abort(
     132             :                 ev->additional_data, struct poll_event_context);
     133             : 
     134         236 :         if (del_idx == UINT64_MAX) {
     135           5 :                 goto done;
     136             :         }
     137             : 
     138         231 :         poll_ev->fdes[del_idx] = NULL;
     139         231 :         poll_ev->deleted = true;
     140         231 :         poll_event_wake_pollthread(poll_ev);
     141         673 : done:
     142         673 :         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         427 : _PRIVATE_ bool tevent_poll_event_add_fd_internal(struct tevent_context *ev,
     165             :                                                  struct tevent_fd *fde)
     166             : {
     167         427 :         struct poll_event_context *poll_ev = talloc_get_type_abort(
     168             :                 ev->additional_data, struct poll_event_context);
     169         427 :         uint64_t fde_idx = UINT64_MAX;
     170         228 :         size_t num_fdes;
     171             : 
     172         427 :         fde->additional_flags = UINT64_MAX;
     173         427 :         tevent_common_fd_mpx_reinit(fde);
     174         427 :         talloc_set_destructor(fde, poll_event_fd_destructor);
     175             : 
     176         427 :         if (fde->flags == 0) {
     177             :                 /*
     178             :                  * Nothing more to do...
     179             :                  */
     180           0 :                 return true;
     181             :         }
     182             : 
     183             :         /*
     184             :          * We need to add it to the end of the 'fdes' array.
     185             :          */
     186         388 :         num_fdes = poll_ev->num_fdes + 1;
     187         388 :         if (num_fdes > talloc_array_length(poll_ev->fdes)) {
     188          33 :                 struct tevent_fd **tmp_fdes = NULL;
     189          26 :                 size_t array_length;
     190             : 
     191          33 :                 array_length = (num_fdes + 15) & ~15; /* round up to 16 */
     192             : 
     193          33 :                 tmp_fdes = talloc_realloc(poll_ev,
     194             :                                           poll_ev->fdes,
     195             :                                           struct tevent_fd *,
     196             :                                           array_length);
     197          33 :                 if (tmp_fdes == NULL) {
     198           0 :                         return false;
     199             :                 }
     200          33 :                 poll_ev->fdes = tmp_fdes;
     201             :         }
     202             : 
     203         388 :         fde_idx = poll_ev->num_fdes;
     204         388 :         fde->additional_flags = fde_idx;
     205         388 :         poll_ev->fdes[fde_idx] = fde;
     206         388 :         poll_ev->num_fdes++;
     207             : 
     208         388 :         return true;
     209             : }
     210             : 
     211             : /*
     212             :   add a fd based event
     213             :   return NULL on failure (memory allocation error)
     214             : */
     215         294 : static struct tevent_fd *poll_event_add_fd(struct tevent_context *ev,
     216             :                                            TALLOC_CTX *mem_ctx,
     217             :                                            int fd, uint16_t flags,
     218             :                                            tevent_fd_handler_t handler,
     219             :                                            void *private_data,
     220             :                                            const char *handler_name,
     221             :                                            const char *location)
     222             : {
     223         294 :         struct poll_event_context *poll_ev = talloc_get_type_abort(
     224             :                 ev->additional_data, struct poll_event_context);
     225         100 :         struct tevent_fd *fde;
     226         100 :         bool ok;
     227             : 
     228         294 :         if (fd < 0) {
     229           0 :                 return NULL;
     230             :         }
     231             : 
     232         294 :         fde = tevent_common_add_fd(ev,
     233             :                                    mem_ctx,
     234             :                                    fd,
     235             :                                    flags,
     236             :                                    handler,
     237             :                                    private_data,
     238             :                                    handler_name,
     239             :                                    location);
     240         294 :         if (fde == NULL) {
     241           0 :                 return NULL;
     242             :         }
     243             : 
     244         294 :         ok = tevent_poll_event_add_fd_internal(ev, fde);
     245         294 :         if (!ok) {
     246           0 :                 TALLOC_FREE(fde);
     247           0 :                 return NULL;
     248             :         }
     249         294 :         poll_event_wake_pollthread(poll_ev);
     250             : 
     251             :         /*
     252             :          * poll_event_loop_poll will take care of the rest in
     253             :          * poll_event_setup_fresh
     254             :          */
     255         194 :         return fde;
     256             : }
     257             : 
     258             : /*
     259             :   map from TEVENT_FD_* to POLLIN/POLLOUT
     260             : */
     261         387 : static uint16_t poll_map_flags(uint16_t flags)
     262             : {
     263         387 :         uint16_t pollflags = 0;
     264             : 
     265             :         /*
     266             :          * we do not need to specify POLLERR | POLLHUP
     267             :          * they are always reported.
     268             :          */
     269             : 
     270         387 :         if (flags & TEVENT_FD_READ) {
     271         339 :                 pollflags |= POLLIN;
     272             : #ifdef POLLRDHUP
     273             :                 /*
     274             :                  * Note that at least on Linux
     275             :                  * POLLRDHUP always returns
     276             :                  * POLLIN in addition, so this
     277             :                  * is not strictly needed, but
     278             :                  * we want to make it explicit.
     279             :                  */
     280         339 :                 pollflags |= POLLRDHUP;
     281             : #endif
     282             :         }
     283         387 :         if (flags & TEVENT_FD_WRITE) {
     284         122 :                 pollflags |= POLLOUT;
     285             :         }
     286         387 :         if (flags & TEVENT_FD_ERROR) {
     287             : #ifdef POLLRDHUP
     288          76 :                 pollflags |= POLLRDHUP;
     289             : #endif
     290             :         }
     291             : 
     292         387 :         return pollflags;
     293             : }
     294             : 
     295             : /*
     296             :   set the fd event flags
     297             : */
     298         294 : static void poll_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
     299             : {
     300         294 :         struct tevent_context *ev = fde->event_ctx;
     301         292 :         struct poll_event_context *poll_ev;
     302         294 :         uint64_t idx = fde->additional_flags;
     303             : 
     304         294 :         if (ev == NULL) {
     305           0 :                 return;
     306             :         }
     307             : 
     308         294 :         if (fde->flags == flags) {
     309           2 :                 return;
     310             :         }
     311             : 
     312         270 :         poll_ev = talloc_get_type_abort(
     313             :                 ev->additional_data, struct poll_event_context);
     314             : 
     315         270 :         fde->flags = flags;
     316             : 
     317         270 :         if (idx == UINT64_MAX) {
     318             :                 /*
     319             :                  * We move it between the fresh and disabled lists.
     320             :                  */
     321         128 :                 tevent_poll_event_add_fd_internal(ev, fde);
     322         128 :                 poll_event_wake_pollthread(poll_ev);
     323         128 :                 return;
     324             :         }
     325             : 
     326         142 :         if (fde->flags == 0) {
     327             :                 /*
     328             :                  * We need to remove it from the array
     329             :                  * and move it to the disabled list.
     330             :                  */
     331         134 :                 poll_ev->fdes[idx] = NULL;
     332         134 :                 poll_ev->deleted = true;
     333         134 :                 fde->additional_flags = UINT64_MAX;
     334         134 :                 poll_event_wake_pollthread(poll_ev);
     335         134 :                 return;
     336             :         }
     337             : 
     338           8 :         if (idx >= poll_ev->num_fds) {
     339             :                 /*
     340             :                  * Not yet added to the
     341             :                  * poll_ev->fds array.
     342             :                  */
     343           2 :                 poll_event_wake_pollthread(poll_ev);
     344           2 :                 return;
     345             :         }
     346             : 
     347           6 :         poll_ev->fds[idx].events = poll_map_flags(flags);
     348             : 
     349           6 :         poll_event_wake_pollthread(poll_ev);
     350             : }
     351             : 
     352    13880830 : static bool poll_event_sync_arrays(struct tevent_context *ev,
     353             :                                    struct poll_event_context *poll_ev)
     354             : {
     355    13880078 :         size_t i;
     356    13880078 :         size_t array_length;
     357             : 
     358    13880830 :         if (poll_ev->deleted) {
     359             : 
     360         996 :                 for (i=0; i < poll_ev->num_fds;) {
     361         776 :                         struct tevent_fd *fde = poll_ev->fdes[i];
     362         212 :                         size_t ci;
     363             : 
     364         776 :                         if (fde != NULL) {
     365         456 :                                 i++;
     366         456 :                                 continue;
     367             :                         }
     368             : 
     369             :                         /*
     370             :                          * This fde was talloc_free()'ed. Delete it
     371             :                          * from the arrays
     372             :                          */
     373         320 :                         poll_ev->num_fds -= 1;
     374         320 :                         ci = poll_ev->num_fds;
     375         320 :                         if (ci > i) {
     376         104 :                                 poll_ev->fds[i] = poll_ev->fds[ci];
     377         104 :                                 poll_ev->fdes[i] = poll_ev->fdes[ci];
     378         104 :                                 if (poll_ev->fdes[i] != NULL) {
     379           4 :                                         poll_ev->fdes[i]->additional_flags = i;
     380             :                                 }
     381             :                         }
     382         320 :                         poll_ev->fds[ci] = (struct pollfd) { .fd = -1 };
     383         320 :                         poll_ev->fdes[ci] = NULL;
     384             :                 }
     385         220 :                 poll_ev->deleted = false;
     386             :         }
     387             : 
     388    13880830 :         if (poll_ev->num_fds == poll_ev->num_fdes) {
     389         558 :                 return true;
     390             :         }
     391             : 
     392             :         /*
     393             :          * Recheck the size of both arrays and make sure
     394             :          * poll_fd->fds array has at least the size of the
     395             :          * in use poll_ev->fdes array.
     396             :          */
     397         263 :         if (poll_ev->num_fdes > talloc_array_length(poll_ev->fds)) {
     398          28 :                 struct pollfd *tmp_fds = NULL;
     399             : 
     400             :                 /*
     401             :                  * Make sure both allocated the same length.
     402             :                  */
     403          28 :                 array_length = talloc_array_length(poll_ev->fdes);
     404             : 
     405          28 :                 tmp_fds = talloc_realloc(poll_ev,
     406             :                                          poll_ev->fds,
     407             :                                          struct pollfd,
     408             :                                          array_length);
     409          28 :                 if (tmp_fds == NULL) {
     410           0 :                         return false;
     411             :                 }
     412          28 :                 poll_ev->fds = tmp_fds;
     413             :         }
     414             : 
     415             :         /*
     416             :          * Now setup the new elements.
     417             :          */
     418         964 :         for (i = poll_ev->num_fds; i < poll_ev->num_fdes; i++) {
     419         701 :                 struct tevent_fd *fde = poll_ev->fdes[i];
     420         701 :                 struct pollfd *pfd = &poll_ev->fds[poll_ev->num_fds];
     421             : 
     422         701 :                 if (fde == NULL) {
     423         320 :                         continue;
     424             :                 }
     425             : 
     426         381 :                 if (i > poll_ev->num_fds) {
     427         192 :                         poll_ev->fdes[poll_ev->num_fds] = fde;
     428         192 :                         fde->additional_flags = poll_ev->num_fds;
     429         192 :                         poll_ev->fdes[i] = NULL;
     430             :                 }
     431             : 
     432         381 :                 pfd->fd = fde->fd;
     433         381 :                 pfd->events = poll_map_flags(fde->flags);
     434         381 :                 pfd->revents = 0;
     435             : 
     436         381 :                 poll_ev->num_fds += 1;
     437             :         }
     438             :         /* Both are in sync again */
     439         263 :         poll_ev->num_fdes = poll_ev->num_fds;
     440             : 
     441             :         /*
     442             :          * Check if we should shrink the arrays
     443             :          * But keep at least 16 elements.
     444             :          */
     445             : 
     446         263 :         array_length = (poll_ev->num_fds + 15) & ~15; /* round up to 16 */
     447         263 :         array_length = MAX(array_length, 16);
     448         263 :         if (array_length < talloc_array_length(poll_ev->fdes)) {
     449           5 :                 struct tevent_fd **tmp_fdes = NULL;
     450           5 :                 struct pollfd *tmp_fds = NULL;
     451             : 
     452           5 :                 tmp_fdes = talloc_realloc(poll_ev,
     453             :                                           poll_ev->fdes,
     454             :                                           struct tevent_fd *,
     455             :                                           array_length);
     456           5 :                 if (tmp_fdes == NULL) {
     457           0 :                         return false;
     458             :                 }
     459           5 :                 poll_ev->fdes = tmp_fdes;
     460             : 
     461           5 :                 tmp_fds = talloc_realloc(poll_ev,
     462             :                                          poll_ev->fds,
     463             :                                          struct pollfd,
     464             :                                          array_length);
     465           5 :                 if (tmp_fds == NULL) {
     466           0 :                         return false;
     467             :                 }
     468           5 :                 poll_ev->fds = tmp_fds;
     469             :         }
     470             : 
     471         194 :         return true;
     472             : }
     473             : 
     474             : /*
     475             :   event loop handling using poll()
     476             : */
     477    13880830 : static int poll_event_loop_poll(struct tevent_context *ev,
     478             :                                 struct timeval *tvalp)
     479             : {
     480    13880830 :         struct poll_event_context *poll_ev = talloc_get_type_abort(
     481             :                 ev->additional_data, struct poll_event_context);
     482    13880078 :         int pollrtn;
     483    13880830 :         int timeout = -1;
     484    13880078 :         int poll_errno;
     485    13880830 :         struct tevent_fd *fde = NULL;
     486    13880830 :         struct tevent_fd *next = NULL;
     487    13880078 :         unsigned i;
     488    13880078 :         bool ok;
     489             : 
     490    13880830 :         if (ev->signal_events && tevent_common_check_signal(ev)) {
     491           0 :                 return 0;
     492             :         }
     493             : 
     494    13880830 :         if (tvalp != NULL) {
     495    13880830 :                 timeout = tvalp->tv_sec * 1000;
     496    13880830 :                 timeout += (tvalp->tv_usec + 999) / 1000;
     497             :         }
     498             : 
     499    13880830 :         ok = poll_event_sync_arrays(ev, poll_ev);
     500    13880830 :         if (!ok) {
     501           0 :                 return -1;
     502             :         }
     503             : 
     504    13880830 :         tevent_trace_point_callback(poll_ev->ev, TEVENT_TRACE_BEFORE_WAIT);
     505    13880830 :         pollrtn = poll(poll_ev->fds, poll_ev->num_fds, timeout);
     506    13880830 :         poll_errno = errno;
     507    13880830 :         tevent_trace_point_callback(poll_ev->ev, TEVENT_TRACE_AFTER_WAIT);
     508             : 
     509    13880830 :         if (pollrtn == -1 && poll_errno == EINTR && ev->signal_events) {
     510           0 :                 tevent_common_check_signal(ev);
     511           0 :                 return 0;
     512             :         }
     513             : 
     514    13880830 :         if (pollrtn == 0 && tvalp) {
     515             :                 /* we don't care about a possible delay here */
     516          18 :                 tevent_common_loop_timer_delay(ev);
     517          18 :                 return 0;
     518             :         }
     519             : 
     520    13880812 :         if (pollrtn <= 0) {
     521             :                 /*
     522             :                  * No fd's ready
     523             :                  */
     524           0 :                 return 0;
     525             :         }
     526             : 
     527             :         /* at least one file descriptor is ready - check
     528             :            which ones and call the handler, being careful to allow
     529             :            the handler to remove itself when called */
     530             : 
     531    47675789 :         for (fde = ev->fd_events; fde; fde = next) {
     532    47675789 :                 uint64_t idx = fde->additional_flags;
     533    47673917 :                 struct pollfd *pfd;
     534    47675789 :                 uint16_t flags = 0;
     535             : 
     536    47675789 :                 next = fde->next;
     537             : 
     538    47675789 :                 if (idx == UINT64_MAX) {
     539       32493 :                         continue;
     540             :                 }
     541             : 
     542    47643296 :                 pfd = &poll_ev->fds[idx];
     543             : 
     544    47643296 :                 if (pfd->revents & POLLNVAL) {
     545             :                         /*
     546             :                          * the socket is dead! this should never
     547             :                          * happen as the socket should have first been
     548             :                          * made readable and that should have removed
     549             :                          * the event, so this must be a bug.
     550             :                          *
     551             :                          * We ignore it here to match the epoll
     552             :                          * behavior.
     553             :                          */
     554           0 :                         tevent_debug(ev, TEVENT_DEBUG_ERROR,
     555             :                                      "POLLNVAL on fde[%p] fd[%d] - disabling\n",
     556             :                                      fde, pfd->fd);
     557           0 :                         poll_ev->fdes[idx] = NULL;
     558           0 :                         poll_ev->deleted = true;
     559           0 :                         tevent_common_fd_disarm(fde);
     560           0 :                         continue;
     561             :                 }
     562             : 
     563             : #ifdef POLLRDHUP
     564             : #define __POLL_RETURN_ERROR_FLAGS (POLLHUP|POLLERR|POLLRDHUP)
     565             : #else
     566             : #define __POLL_RETURN_ERROR_FLAGS (POLLHUP|POLLERR)
     567             : #endif
     568             : 
     569    47643296 :                 if (pfd->revents & __POLL_RETURN_ERROR_FLAGS) {
     570             :                         /*
     571             :                          * If we only wait for TEVENT_FD_WRITE, we
     572             :                          * should not tell the event handler about it,
     573             :                          * and remove the writable flag, as we only
     574             :                          * report errors when waiting for read events
     575             :                          * or explicit for errors.
     576             :                          */
     577        1788 :                         if (!(fde->flags & (TEVENT_FD_READ|TEVENT_FD_ERROR)))
     578             :                         {
     579           2 :                                 TEVENT_FD_NOT_WRITEABLE(fde);
     580           2 :                                 continue;
     581             :                         }
     582        1786 :                         if (fde->flags & TEVENT_FD_ERROR) {
     583        1016 :                                 flags |= TEVENT_FD_ERROR;
     584             :                         }
     585        1786 :                         if (fde->flags & TEVENT_FD_READ) {
     586        1278 :                                 flags |= TEVENT_FD_READ;
     587             :                         }
     588             :                 }
     589    47643294 :                 if (pfd->revents & POLLIN) {
     590     7254068 :                         flags |= TEVENT_FD_READ;
     591             :                 }
     592    47643294 :                 if (pfd->revents & POLLOUT) {
     593     6630608 :                         flags |= TEVENT_FD_WRITE;
     594             :                 }
     595             :                 /*
     596             :                  * Note that fde->flags could be changed when using
     597             :                  * the poll_mt backend together with threads,
     598             :                  * that why we need to check pfd->revents and fde->flags
     599             :                  */
     600    47643294 :                 flags &= fde->flags;
     601    47643294 :                 if (flags != 0) {
     602    13880812 :                         DLIST_DEMOTE(ev->fd_events, fde);
     603    13880812 :                         return tevent_common_invoke_fd_handler(fde, flags, NULL);
     604             :                 }
     605             :         }
     606             : 
     607           0 :         for (i = 0; i < poll_ev->num_fds; i++) {
     608           0 :                 if (poll_ev->fds[i].revents & POLLNVAL) {
     609             :                         /*
     610             :                          * the socket is dead! this should never
     611             :                          * happen as the socket should have first been
     612             :                          * made readable and that should have removed
     613             :                          * the event, so this must be a bug or
     614             :                          * a race in the poll_mt usage.
     615             :                          */
     616           0 :                         fde = poll_ev->fdes[i];
     617           0 :                         tevent_debug(ev, TEVENT_DEBUG_WARNING,
     618             :                                      "POLLNVAL on dangling fd[%d] fde[%p] - disabling\n",
     619           0 :                                      poll_ev->fds[i].fd, fde);
     620           0 :                         poll_ev->fdes[i] = NULL;
     621           0 :                         poll_ev->deleted = true;
     622           0 :                         if (fde != NULL) {
     623           0 :                                 tevent_common_fd_disarm(fde);
     624             :                         }
     625             :                 }
     626             :         }
     627             : 
     628           0 :         return 0;
     629             : }
     630             : 
     631             : /*
     632             :   do a single event loop using the events defined in ev
     633             : */
     634    14503381 : static int poll_event_loop_once(struct tevent_context *ev,
     635             :                                 const char *location)
     636             : {
     637    14502253 :         struct timeval tval;
     638             : 
     639    16992042 :         if (ev->signal_events &&
     640     2488661 :             tevent_common_check_signal(ev)) {
     641           0 :                 return 0;
     642             :         }
     643             : 
     644    13881213 :         if (ev->threaded_contexts != NULL) {
     645           2 :                 tevent_common_threaded_activate_immediate(ev);
     646             :         }
     647             : 
     648    13881592 :         if (ev->immediate_events &&
     649         379 :             tevent_common_loop_immediate(ev)) {
     650         376 :                 return 0;
     651             :         }
     652             : 
     653    13880834 :         tval = tevent_common_loop_timer_delay(ev);
     654    13880834 :         if (tevent_timeval_is_zero(&tval)) {
     655           0 :                 return 0;
     656             :         }
     657             : 
     658    13880830 :         return poll_event_loop_poll(ev, &tval);
     659             : }
     660             : 
     661             : static const struct tevent_ops poll_event_ops = {
     662             :         .context_init           = poll_event_context_init,
     663             :         .add_fd                 = poll_event_add_fd,
     664             :         .set_fd_close_fn        = tevent_common_fd_set_close_fn,
     665             :         .get_fd_flags           = tevent_common_fd_get_flags,
     666             :         .set_fd_flags           = poll_event_set_fd_flags,
     667             :         .add_timer              = tevent_common_add_timer_v2,
     668             :         .schedule_immediate     = tevent_common_schedule_immediate,
     669             :         .add_signal             = tevent_common_add_signal,
     670             :         .loop_once              = poll_event_loop_once,
     671             :         .loop_wait              = tevent_common_loop_wait,
     672             : };
     673             : 
     674       76842 : _PRIVATE_ bool tevent_poll_init(void)
     675             : {
     676       76842 :         return tevent_register_backend("poll", &poll_event_ops);
     677             : }
     678             : 
     679             : static const struct tevent_ops poll_event_mt_ops = {
     680             :         .context_init           = poll_event_context_init_mt,
     681             :         .add_fd                 = poll_event_add_fd,
     682             :         .set_fd_close_fn        = tevent_common_fd_set_close_fn,
     683             :         .get_fd_flags           = tevent_common_fd_get_flags,
     684             :         .set_fd_flags           = poll_event_set_fd_flags,
     685             :         .add_timer              = tevent_common_add_timer_v2,
     686             :         .schedule_immediate     = poll_event_schedule_immediate,
     687             :         .add_signal             = tevent_common_add_signal,
     688             :         .loop_once              = poll_event_loop_once,
     689             :         .loop_wait              = tevent_common_loop_wait,
     690             : };
     691             : 
     692       76842 : _PRIVATE_ bool tevent_poll_mt_init(void)
     693             : {
     694       76842 :         return tevent_register_backend("poll_mt", &poll_event_mt_ops);
     695             : }

Generated by: LCOV version 1.14