LCOV - code coverage report
Current view: top level - lib/tevent - testsuite.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 959 1143 83.9 %
Date: 2023-11-21 12:31:41 Functions: 67 77 87.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    testing of the events subsystem
       5             : 
       6             :    Copyright (C) Stefan Metzmacher 2006-2009
       7             :    Copyright (C) Jeremy Allison    2013
       8             : 
       9             :      ** NOTE! The following LGPL license applies to the tevent
      10             :      ** library. This does NOT imply that all of Samba is released
      11             :      ** under the LGPL
      12             : 
      13             :    This library is free software; you can redistribute it and/or
      14             :    modify it under the terms of the GNU Lesser General Public
      15             :    License as published by the Free Software Foundation; either
      16             :    version 3 of the License, or (at your option) any later version.
      17             : 
      18             :    This library is distributed in the hope that it will be useful,
      19             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      20             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      21             :    Lesser General Public License for more details.
      22             : 
      23             :    You should have received a copy of the GNU Lesser General Public
      24             :    License along with this library; if not, see <http://www.gnu.org/licenses/>.
      25             : */
      26             : 
      27             : #include "includes.h"
      28             : #define TEVENT_DEPRECATED 1
      29             : #include "tevent.h"
      30             : #include "system/filesys.h"
      31             : #include "system/select.h"
      32             : #include "system/network.h"
      33             : #include "torture/torture.h"
      34             : #include "torture/local/proto.h"
      35             : #include "lib/util/blocking.h"
      36             : #ifdef HAVE_PTHREAD
      37             : #include "system/threads.h"
      38             : #include <assert.h>
      39             : #endif
      40             : 
      41             : static struct tevent_context *
      42           3 : test_tevent_context_init(TALLOC_CTX *mem_ctx)
      43             : {
      44           3 :         struct tevent_context *ev = NULL;
      45             : 
      46           3 :         ev = tevent_context_init(mem_ctx);
      47           3 :         if (ev != NULL) {
      48           3 :                 samba_tevent_set_debug(ev, "<default>");
      49             :         }
      50             : 
      51           3 :         return ev;
      52             : }
      53             : 
      54             : static struct tevent_context *
      55          37 : test_tevent_context_init_byname(TALLOC_CTX *mem_ctx, const char *name)
      56             : {
      57          37 :         struct tevent_context *ev = NULL;
      58             : 
      59          37 :         ev = tevent_context_init_byname(mem_ctx, name);
      60          37 :         if (ev != NULL) {
      61          37 :                 samba_tevent_set_debug(ev, name);
      62             :         }
      63             : 
      64          37 :         return ev;
      65             : }
      66             : 
      67             : static int fde_count;
      68             : 
      69    13296816 : static void do_read(int fd, void *buf, size_t count)
      70             : {
      71    13296816 :         ssize_t ret;
      72             : 
      73    13296816 :         do {
      74    13296816 :                 ret = read(fd, buf, count);
      75    13296816 :         } while (ret == -1 && errno == EINTR);
      76    13296816 : }
      77             : 
      78     1296816 : static void fde_handler_read(struct tevent_context *ev_ctx, struct tevent_fd *f,
      79             :                         uint16_t flags, void *private_data)
      80             : {
      81     1296816 :         int *fd = (int *)private_data;
      82     1296816 :         char c;
      83             : #ifdef SA_SIGINFO
      84     1296816 :         kill(getpid(), SIGUSR1);
      85             : #endif
      86     1296816 :         kill(getpid(), SIGALRM);
      87             : 
      88     1296816 :         do_read(fd[0], &c, 1);
      89     1296816 :         fde_count++;
      90     1296816 : }
      91             : 
      92    13296863 : static void do_write(int fd, void *buf, size_t count)
      93             : {
      94    13296863 :         ssize_t ret;
      95             : 
      96    13296863 :         do {
      97    13296863 :                 ret = write(fd, buf, count);
      98    13296863 :         } while (ret == -1 && errno == EINTR);
      99    13296863 : }
     100             : 
     101           8 : static void do_fill(int fd)
     102             : {
     103           8 :         uint8_t buf[1024] = {0, };
     104           8 :         ssize_t ret;
     105             : 
     106           8 :         set_blocking(fd, false);
     107             : 
     108         752 :         do {
     109         752 :                 do {
     110         752 :                         ret = write(fd, buf, ARRAY_SIZE(buf));
     111         752 :                 } while (ret == -1 && errno == EINTR);
     112         752 :         } while (ret == ARRAY_SIZE(buf));
     113             : 
     114           8 :         set_blocking(fd, true);
     115           8 : }
     116             : 
     117     1296819 : static void fde_handler_write(struct tevent_context *ev_ctx, struct tevent_fd *f,
     118             :                         uint16_t flags, void *private_data)
     119             : {
     120     1296819 :         int *fd = (int *)private_data;
     121     1296819 :         char c = 0;
     122             : 
     123     1296819 :         do_write(fd[1], &c, 1);
     124     1296819 : }
     125             : 
     126             : 
     127             : /* This will only fire if the fd's returned from pipe() are bi-directional. */
     128           0 : static void fde_handler_read_1(struct tevent_context *ev_ctx, struct tevent_fd *f,
     129             :                         uint16_t flags, void *private_data)
     130             : {
     131           0 :         int *fd = (int *)private_data;
     132           0 :         char c;
     133             : #ifdef SA_SIGINFO
     134           0 :         kill(getpid(), SIGUSR1);
     135             : #endif
     136           0 :         kill(getpid(), SIGALRM);
     137             : 
     138           0 :         do_read(fd[1], &c, 1);
     139           0 :         fde_count++;
     140           0 : }
     141             : 
     142             : /* This will only fire if the fd's returned from pipe() are bi-directional. */
     143           0 : static void fde_handler_write_1(struct tevent_context *ev_ctx, struct tevent_fd *f,
     144             :                         uint16_t flags, void *private_data)
     145             : {
     146           0 :         int *fd = (int *)private_data;
     147           0 :         char c = 0;
     148           0 :         do_write(fd[0], &c, 1);
     149           0 : }
     150             : 
     151           4 : static void finished_handler(struct tevent_context *ev_ctx, struct tevent_timer *te,
     152             :                              struct timeval tval, void *private_data)
     153             : {
     154           4 :         int *finished = (int *)private_data;
     155           4 :         (*finished) = 1;
     156           4 : }
     157             : 
     158     2593636 : static void count_handler(struct tevent_context *ev_ctx, struct tevent_signal *te,
     159             :                           int signum, int count, void *info, void *private_data)
     160             : {
     161     2593636 :         int *countp = (int *)private_data;
     162     2593636 :         (*countp) += count;
     163     2593636 : }
     164             : 
     165           4 : static bool test_event_context(struct torture_context *test,
     166             :                                const void *test_data)
     167             : {
     168           4 :         struct tevent_context *ev_ctx;
     169           4 :         int fd[2] = { -1, -1 };
     170           4 :         const char *backend = (const char *)test_data;
     171           4 :         int alarm_count=0, info_count=0;
     172           4 :         struct tevent_fd *fde_read;
     173           4 :         struct tevent_fd *fde_read_1;
     174           4 :         struct tevent_fd *fde_write;
     175           4 :         struct tevent_fd *fde_write_1;
     176             : #ifdef SA_RESTART
     177           4 :         struct tevent_signal *se1 = NULL;
     178             : #endif
     179             : #ifdef SA_RESETHAND
     180           4 :         struct tevent_signal *se2 = NULL;
     181             : #endif
     182             : #ifdef SA_SIGINFO
     183           4 :         struct tevent_signal *se3 = NULL;
     184             : #endif
     185           4 :         int finished=0;
     186           4 :         struct timeval t;
     187           4 :         int ret;
     188             : 
     189           4 :         ev_ctx = test_tevent_context_init_byname(test, backend);
     190           4 :         if (ev_ctx == NULL) {
     191           0 :                 torture_comment(test, "event backend '%s' not supported\n", backend);
     192           0 :                 return true;
     193             :         }
     194             : 
     195           4 :         torture_comment(test, "backend '%s' - %s\n",
     196             :                         backend, __FUNCTION__);
     197             : 
     198             :         /* reset globals */
     199           4 :         fde_count = 0;
     200             : 
     201             :         /* create a pipe */
     202           4 :         ret = pipe(fd);
     203           4 :         torture_assert_int_equal(test, ret, 0, "pipe failed");
     204             : 
     205           4 :         fde_read = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_READ,
     206             :                             fde_handler_read, fd);
     207           4 :         fde_write_1 = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_WRITE,
     208             :                             fde_handler_write_1, fd);
     209             : 
     210           4 :         fde_write = tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_WRITE,
     211             :                             fde_handler_write, fd);
     212           4 :         fde_read_1 = tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_READ,
     213             :                             fde_handler_read_1, fd);
     214             : 
     215           4 :         tevent_fd_set_auto_close(fde_read);
     216           4 :         tevent_fd_set_auto_close(fde_write);
     217             : 
     218           4 :         tevent_add_timer(ev_ctx, ev_ctx, timeval_current_ofs(2,0),
     219             :                          finished_handler, &finished);
     220             : 
     221             : #ifdef SA_RESTART
     222           4 :         se1 = tevent_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESTART, count_handler, &alarm_count);
     223           4 :         torture_assert(test, se1 != NULL, "failed to setup se1");
     224             : #endif
     225             : #ifdef SA_RESETHAND
     226           4 :         se2 = tevent_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESETHAND, count_handler, &alarm_count);
     227           4 :         torture_assert(test, se2 != NULL, "failed to setup se2");
     228             : #endif
     229             : #ifdef SA_SIGINFO
     230           4 :         se3 = tevent_add_signal(ev_ctx, ev_ctx, SIGUSR1, SA_SIGINFO, count_handler, &info_count);
     231           4 :         torture_assert(test, se3 != NULL, "failed to setup se3");
     232             : #endif
     233             : 
     234           4 :         t = timeval_current();
     235     5187272 :         while (!finished) {
     236     5187268 :                 errno = 0;
     237     5187268 :                 if (tevent_loop_once(ev_ctx) == -1) {
     238           0 :                         TALLOC_FREE(ev_ctx);
     239           0 :                         torture_fail(test, talloc_asprintf(test, "Failed event loop %s\n", strerror(errno)));
     240             :                         return false;
     241             :                 }
     242             :         }
     243             : 
     244           4 :         talloc_free(fde_read_1);
     245           4 :         talloc_free(fde_write_1);
     246           4 :         talloc_free(fde_read);
     247           4 :         talloc_free(fde_write);
     248             : 
     249           4 :         while (alarm_count < fde_count+1) {
     250           0 :                 if (tevent_loop_once(ev_ctx) == -1) {
     251           0 :                         break;
     252             :                 }
     253             :         }
     254             : 
     255           4 :         torture_comment(test, "Got %.2f pipe events/sec\n", fde_count/timeval_elapsed(&t));
     256             : 
     257             : #ifdef SA_RESTART
     258           4 :         talloc_free(se1);
     259             : #endif
     260             : 
     261           4 :         torture_assert_int_equal(test, alarm_count, 1+fde_count, "alarm count mismatch");
     262             : 
     263             : #ifdef SA_RESETHAND
     264             :         /*
     265             :          * we do not call talloc_free(se2)
     266             :          * because it is already gone,
     267             :          * after triggering the event handler.
     268             :          */
     269             : #endif
     270             : 
     271             : #ifdef SA_SIGINFO
     272           4 :         talloc_free(se3);
     273           4 :         torture_assert_int_equal(test, info_count, fde_count, "info count mismatch");
     274             : #endif
     275             : 
     276           4 :         talloc_free(ev_ctx);
     277             : 
     278           4 :         return true;
     279             : }
     280             : 
     281    12000000 : static void fde_handler_do_read(struct tevent_context *ev_ctx, struct tevent_fd *f,
     282             :                         uint16_t flags, void *private_data)
     283             : {
     284    12000000 :         int *fd = (int *)private_data;
     285    12000000 :         char c = 0;
     286             : 
     287    12000000 :         do_read(fd[0], &c, 1);
     288    12000000 :         fde_count++;
     289    12000000 : }
     290             : 
     291    12000006 : static void fde_handler_do_write(struct tevent_context *ev_ctx, struct tevent_fd *f,
     292             :                         uint16_t flags, void *private_data)
     293             : {
     294    12000006 :         int *fd = (int *)private_data;
     295    12000006 :         char c = 0;
     296             : 
     297    12000006 :         do_write(fd[1], &c, 1);
     298    12000006 : }
     299             : 
     300           0 : static void fde_handler_ignore(struct tevent_context *ev_ctx, struct tevent_fd *f,
     301             :                         uint16_t flags, void *private_data)
     302             : {
     303           0 : }
     304             : 
     305          12 : static bool test_fd_speedX(struct torture_context *test,
     306             :                            const void *test_data,
     307             :                            size_t additional_fdes)
     308             : {
     309          12 :         struct tevent_context *ev_ctx = NULL;
     310          12 :         int fd[2] = { -1, -1 };
     311          12 :         const char *backend = (const char *)test_data;
     312          12 :         struct tevent_fd *fde_read = NULL;
     313          12 :         struct tevent_fd *fde_write = NULL;
     314          12 :         int finished=0;
     315          12 :         struct timeval t;
     316          12 :         size_t i;
     317          12 :         int ret;
     318             : 
     319          12 :         ev_ctx = test_tevent_context_init_byname(test, backend);
     320          12 :         if (ev_ctx == NULL) {
     321           0 :                 torture_comment(test, "event backend '%s' not supported\n", backend);
     322           0 :                 return true;
     323             :         }
     324             : 
     325          12 :         torture_comment(test, "backend '%s' - test_fd_speed%zu\n",
     326             :                         backend, 1 + additional_fdes);
     327             : 
     328             :         /* reset globals */
     329          12 :         fde_count = 0;
     330             : 
     331             :         /* create a pipe */
     332          12 :         ret = pipe(fd);
     333          12 :         torture_assert_int_equal(test, ret, 0, "pipe failed");
     334             : 
     335          12 :         fde_read = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_READ,
     336             :                                  fde_handler_do_read, fd);
     337             : 
     338          12 :         fde_write = tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_WRITE,
     339             :                                   fde_handler_do_write, fd);
     340             : 
     341          36 :         for (i = 0; i < additional_fdes; i++) {
     342          12 :                 tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_WRITE,
     343             :                               fde_handler_ignore, fd);
     344          12 :                 tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_READ,
     345             :                               fde_handler_ignore, fd);
     346             :         }
     347             : 
     348          12 :         tevent_fd_set_auto_close(fde_read);
     349          12 :         tevent_fd_set_auto_close(fde_write);
     350             : 
     351          12 :         tevent_add_timer(ev_ctx, ev_ctx, timeval_current_ofs(600,0),
     352             :                          finished_handler, &finished);
     353             : 
     354          12 :         t = timeval_current();
     355    24000021 :         while (!finished && fde_count < 1000000) {
     356    24000009 :                 errno = 0;
     357    24000009 :                 if (tevent_loop_once(ev_ctx) == -1) {
     358           0 :                         TALLOC_FREE(ev_ctx);
     359           0 :                         torture_fail(test, talloc_asprintf(test, "Failed event loop %s\n", strerror(errno)));
     360             :                         return false;
     361             :                 }
     362             :         }
     363             : 
     364          12 :         talloc_free(fde_read);
     365          12 :         talloc_free(fde_write);
     366             : 
     367          12 :         torture_comment(test, "Got %.2f pipe events\n", (double)fde_count);
     368          12 :         torture_comment(test, "Got %.2f pipe events/sec\n", fde_count/timeval_elapsed(&t));
     369             : 
     370          12 :         talloc_free(ev_ctx);
     371             : 
     372          12 :         return true;
     373             : }
     374             : 
     375           4 : static bool test_fd_speed1(struct torture_context *test,
     376             :                            const void *test_data)
     377             : {
     378           4 :         return test_fd_speedX(test, test_data, 0);
     379             : }
     380             : 
     381           4 : static bool test_fd_speed2(struct torture_context *test,
     382             :                            const void *test_data)
     383             : {
     384           4 :         return test_fd_speedX(test, test_data, 1);
     385             : }
     386             : 
     387           4 : static bool test_fd_speed3(struct torture_context *test,
     388             :                            const void *test_data)
     389             : {
     390           4 :         return test_fd_speedX(test, test_data, 2);
     391             : }
     392             : 
     393             : struct test_event_fd1_state {
     394             :         struct torture_context *tctx;
     395             :         const char *backend;
     396             :         struct tevent_context *ev;
     397             :         int sock[2];
     398             :         struct tevent_timer *te;
     399             :         struct tevent_fd *fde0;
     400             :         struct tevent_fd *fde1;
     401             :         bool got_write;
     402             :         bool got_read;
     403             :         bool drain;
     404             :         bool drain_done;
     405             :         unsigned loop_count;
     406             :         bool finished;
     407             :         const char *error;
     408             : };
     409             : 
     410          40 : static void test_event_fd1_fde_handler(struct tevent_context *ev_ctx,
     411             :                                        struct tevent_fd *fde,
     412             :                                        uint16_t flags,
     413             :                                        void *private_data)
     414             : {
     415          40 :         struct test_event_fd1_state *state =
     416             :                 (struct test_event_fd1_state *)private_data;
     417             : 
     418          40 :         if (state->drain_done) {
     419           0 :                 state->finished = true;
     420           0 :                 state->error = __location__;
     421           0 :                 return;
     422             :         }
     423             : 
     424          40 :         if (state->drain) {
     425          16 :                 ssize_t ret;
     426          16 :                 uint8_t c = 0;
     427             : 
     428          16 :                 if (!(flags & TEVENT_FD_READ)) {
     429           0 :                         state->finished = true;
     430           0 :                         state->error = __location__;
     431           0 :                         return;
     432             :                 }
     433             : 
     434          16 :                 ret = read(state->sock[0], &c, 1);
     435          16 :                 if (ret == 1) {
     436           0 :                         return;
     437             :                 }
     438             : 
     439             :                 /*
     440             :                  * end of test...
     441             :                  */
     442           4 :                 tevent_fd_set_flags(fde, 0);
     443           4 :                 state->drain_done = true;
     444           4 :                 return;
     445             :         }
     446             : 
     447          24 :         if (!state->got_write) {
     448          12 :                 uint8_t c = 0;
     449             : 
     450          12 :                 if (flags != TEVENT_FD_WRITE) {
     451           0 :                         state->finished = true;
     452           0 :                         state->error = __location__;
     453           0 :                         return;
     454             :                 }
     455          12 :                 state->got_write = true;
     456             : 
     457             :                 /*
     458             :                  * we write to the other socket...
     459             :                  */
     460          12 :                 do_write(state->sock[1], &c, 1);
     461          12 :                 TEVENT_FD_NOT_WRITEABLE(fde);
     462          12 :                 TEVENT_FD_READABLE(fde);
     463          12 :                 return;
     464             :         }
     465             : 
     466          12 :         if (!state->got_read) {
     467          12 :                 if (flags != TEVENT_FD_READ) {
     468           0 :                         state->finished = true;
     469           0 :                         state->error = __location__;
     470           0 :                         return;
     471             :                 }
     472          12 :                 state->got_read = true;
     473             : 
     474          12 :                 TEVENT_FD_NOT_READABLE(fde);
     475          12 :                 return;
     476             :         }
     477             : 
     478           0 :         state->finished = true;
     479           0 :         state->error = __location__;
     480           0 :         return;
     481             : }
     482             : 
     483          16 : static void test_event_fd1_finished(struct tevent_context *ev_ctx,
     484             :                                     struct tevent_timer *te,
     485             :                                     struct timeval tval,
     486             :                                     void *private_data)
     487             : {
     488          16 :         struct test_event_fd1_state *state =
     489             :                 (struct test_event_fd1_state *)private_data;
     490             : 
     491          16 :         if (state->drain_done) {
     492           4 :                 state->finished = true;
     493           4 :                 return;
     494             :         }
     495             : 
     496          12 :         if (!state->got_write) {
     497           0 :                 state->finished = true;
     498           0 :                 state->error = __location__;
     499           0 :                 return;
     500             :         }
     501             : 
     502          12 :         if (!state->got_read) {
     503           0 :                 state->finished = true;
     504           0 :                 state->error = __location__;
     505           0 :                 return;
     506             :         }
     507             : 
     508          12 :         state->loop_count++;
     509          12 :         if (state->loop_count > 3) {
     510           0 :                 state->finished = true;
     511           0 :                 state->error = __location__;
     512           0 :                 return;
     513             :         }
     514             : 
     515          12 :         state->got_write = false;
     516          12 :         state->got_read = false;
     517             : 
     518          12 :         tevent_fd_set_flags(state->fde0, TEVENT_FD_WRITE);
     519             : 
     520          12 :         if (state->loop_count > 2) {
     521           4 :                 state->drain = true;
     522           4 :                 TALLOC_FREE(state->fde1);
     523           4 :                 TEVENT_FD_READABLE(state->fde0);
     524             :         }
     525             : 
     526          12 :         state->te = tevent_add_timer(state->ev, state->ev,
     527             :                                     timeval_current_ofs(0,2000),
     528             :                                     test_event_fd1_finished, state);
     529             : }
     530             : 
     531           4 : static bool test_event_fd1(struct torture_context *tctx,
     532             :                            const void *test_data)
     533             : {
     534           4 :         struct test_event_fd1_state state;
     535           4 :         int ret;
     536             : 
     537           4 :         ZERO_STRUCT(state);
     538           4 :         state.tctx = tctx;
     539           4 :         state.backend = (const char *)test_data;
     540             : 
     541           4 :         state.ev = test_tevent_context_init_byname(tctx, state.backend);
     542           4 :         if (state.ev == NULL) {
     543           0 :                 torture_skip(tctx, talloc_asprintf(tctx,
     544             :                              "event backend '%s' not supported\n",
     545             :                              state.backend));
     546             :                 return true;
     547             :         }
     548             : 
     549           4 :         torture_comment(tctx, "backend '%s' - %s\n",
     550             :                         state.backend, __FUNCTION__);
     551             : 
     552             :         /*
     553             :          * This tests the following:
     554             :          *
     555             :          * It monitors the state of state.sock[0]
     556             :          * with tevent_fd, but we never read/write on state.sock[0]
     557             :          * while state.sock[1] * is only used to write a few bytes.
     558             :          *
     559             :          * We have a loop:
     560             :          *   - we wait only for TEVENT_FD_WRITE on state.sock[0]
     561             :          *   - we write 1 byte to state.sock[1]
     562             :          *   - we wait only for TEVENT_FD_READ on state.sock[0]
     563             :          *   - we disable events on state.sock[0]
     564             :          *   - the timer event restarts the loop
     565             :          * Then we close state.sock[1]
     566             :          * We have a loop:
     567             :          *   - we wait for TEVENT_FD_READ/WRITE on state.sock[0]
     568             :          *   - we try to read 1 byte
     569             :          *   - if the read gets an error of returns 0
     570             :          *     we disable the event handler
     571             :          *   - the timer finishes the test
     572             :          */
     573           4 :         state.sock[0] = -1;
     574           4 :         state.sock[1] = -1;
     575             : 
     576           4 :         ret = socketpair(AF_UNIX, SOCK_STREAM, 0, state.sock);
     577           4 :         torture_assert(tctx, ret == 0, "socketpair() failed");
     578             : 
     579           4 :         state.te = tevent_add_timer(state.ev, state.ev,
     580             :                                     timeval_current_ofs(0,10000),
     581             :                                     test_event_fd1_finished, &state);
     582           4 :         state.fde0 = tevent_add_fd(state.ev, state.ev,
     583             :                                    state.sock[0], TEVENT_FD_WRITE,
     584             :                                    test_event_fd1_fde_handler, &state);
     585             :         /* state.fde1 is only used to auto close */
     586           4 :         state.fde1 = tevent_add_fd(state.ev, state.ev,
     587             :                                    state.sock[1], 0,
     588             :                                    test_event_fd1_fde_handler, &state);
     589             : 
     590           4 :         tevent_fd_set_auto_close(state.fde0);
     591           4 :         tevent_fd_set_auto_close(state.fde1);
     592             : 
     593           4 :         while (!state.finished) {
     594          64 :                 errno = 0;
     595          64 :                 if (tevent_loop_once(state.ev) == -1) {
     596           0 :                         talloc_free(state.ev);
     597          68 :                         torture_fail(tctx, talloc_asprintf(tctx,
     598             :                                      "Failed event loop %s\n",
     599             :                                      strerror(errno)));
     600             :                 }
     601             :         }
     602             : 
     603           4 :         talloc_free(state.ev);
     604             : 
     605           4 :         torture_assert(tctx, state.error == NULL, talloc_asprintf(tctx,
     606             :                        "%s", state.error));
     607             : 
     608           0 :         return true;
     609             : }
     610             : 
     611             : struct test_event_fd2_state {
     612             :         struct torture_context *tctx;
     613             :         const char *backend;
     614             :         struct tevent_context *ev;
     615             :         struct tevent_timer *te;
     616             :         struct test_event_fd2_sock {
     617             :                 struct test_event_fd2_state *state;
     618             :                 int fd;
     619             :                 struct tevent_fd *fde;
     620             :                 size_t num_written;
     621             :                 size_t num_read;
     622             :                 bool got_full;
     623             :         } sock0, sock1;
     624             :         bool finished;
     625             :         const char *error;
     626             : };
     627             : 
     628        1116 : static void test_event_fd2_sock_handler(struct tevent_context *ev_ctx,
     629             :                                         struct tevent_fd *fde,
     630             :                                         uint16_t flags,
     631             :                                         void *private_data)
     632             : {
     633        1116 :         struct test_event_fd2_sock *cur_sock =
     634             :                 (struct test_event_fd2_sock *)private_data;
     635        1116 :         struct test_event_fd2_state *state = cur_sock->state;
     636        1116 :         struct test_event_fd2_sock *oth_sock = NULL;
     637        1116 :         uint8_t v = 0, c;
     638        1116 :         ssize_t ret;
     639             : 
     640        1116 :         if (cur_sock == &state->sock0) {
     641         558 :                 oth_sock = &state->sock1;
     642             :         } else {
     643           0 :                 oth_sock = &state->sock0;
     644             :         }
     645             : 
     646        1116 :         if (oth_sock->num_written == 1) {
     647           4 :                 if (flags != (TEVENT_FD_READ | TEVENT_FD_WRITE)) {
     648           0 :                         state->finished = true;
     649           0 :                         state->error = __location__;
     650           0 :                         return;
     651             :                 }
     652             :         }
     653             : 
     654        1116 :         if (cur_sock->num_read == oth_sock->num_written) {
     655           0 :                 state->finished = true;
     656           0 :                 state->error = __location__;
     657           0 :                 return;
     658             :         }
     659             : 
     660        1116 :         if (!(flags & TEVENT_FD_READ)) {
     661           0 :                 state->finished = true;
     662           0 :                 state->error = __location__;
     663           0 :                 return;
     664             :         }
     665             : 
     666        1116 :         if (oth_sock->num_read >= PIPE_BUF) {
     667             :                 /*
     668             :                  * On Linux we become writable once we've read
     669             :                  * one byte. On Solaris we only become writable
     670             :                  * again once we've read 4096 bytes. PIPE_BUF
     671             :                  * is probably a safe bet to test against.
     672             :                  *
     673             :                  * There should be room to write a byte again
     674             :                  */
     675           0 :                 if (!(flags & TEVENT_FD_WRITE)) {
     676           0 :                         state->finished = true;
     677           0 :                         state->error = __location__;
     678           0 :                         return;
     679             :                 }
     680             :         }
     681             : 
     682        1116 :         if ((flags & TEVENT_FD_WRITE) && !cur_sock->got_full) {
     683         552 :                 v = (uint8_t)cur_sock->num_written;
     684         552 :                 ret = write(cur_sock->fd, &v, 1);
     685         552 :                 if (ret != 1) {
     686           0 :                         state->finished = true;
     687           0 :                         state->error = __location__;
     688           0 :                         return;
     689             :                 }
     690         552 :                 cur_sock->num_written++;
     691         552 :                 if (cur_sock->num_written > 0x80000000) {
     692           0 :                         state->finished = true;
     693           0 :                         state->error = __location__;
     694           0 :                         return;
     695             :                 }
     696           0 :                 return;
     697             :         }
     698             : 
     699         564 :         if (!cur_sock->got_full) {
     700           8 :                 cur_sock->got_full = true;
     701             : 
     702           8 :                 if (!oth_sock->got_full) {
     703             :                         /*
     704             :                          * cur_sock is full,
     705             :                          * lets wait for oth_sock
     706             :                          * to be filled
     707             :                          */
     708           4 :                         tevent_fd_set_flags(cur_sock->fde, 0);
     709           4 :                         return;
     710             :                 }
     711             : 
     712             :                 /*
     713             :                  * oth_sock waited for cur_sock,
     714             :                  * lets restart it
     715             :                  */
     716           4 :                 tevent_fd_set_flags(oth_sock->fde,
     717             :                                     TEVENT_FD_READ|TEVENT_FD_WRITE);
     718             :         }
     719             : 
     720         560 :         ret = read(cur_sock->fd, &v, 1);
     721         560 :         if (ret != 1) {
     722           0 :                 state->finished = true;
     723           0 :                 state->error = __location__;
     724           0 :                 return;
     725             :         }
     726         560 :         c = (uint8_t)cur_sock->num_read;
     727         560 :         if (c != v) {
     728           0 :                 state->finished = true;
     729           0 :                 state->error = __location__;
     730           0 :                 return;
     731             :         }
     732         560 :         cur_sock->num_read++;
     733             : 
     734         560 :         if (cur_sock->num_read < oth_sock->num_written) {
     735             :                 /* there is more to read */
     736           0 :                 return;
     737             :         }
     738             :         /*
     739             :          * we read everything, we need to remove TEVENT_FD_WRITE
     740             :          * to avoid spinning
     741             :          */
     742           8 :         TEVENT_FD_NOT_WRITEABLE(cur_sock->fde);
     743             : 
     744           8 :         if (oth_sock->num_read == cur_sock->num_written) {
     745             :                 /*
     746             :                  * both directions are finished
     747             :                  */
     748           4 :                 state->finished = true;
     749             :         }
     750             : 
     751           0 :         return;
     752             : }
     753             : 
     754           0 : static void test_event_fd2_finished(struct tevent_context *ev_ctx,
     755             :                                     struct tevent_timer *te,
     756             :                                     struct timeval tval,
     757             :                                     void *private_data)
     758             : {
     759           0 :         struct test_event_fd2_state *state =
     760             :                 (struct test_event_fd2_state *)private_data;
     761             : 
     762             :         /*
     763             :          * this should never be triggered
     764             :          */
     765           0 :         state->finished = true;
     766           0 :         state->error = __location__;
     767           0 : }
     768             : 
     769           4 : static bool test_event_fd2(struct torture_context *tctx,
     770             :                            const void *test_data)
     771             : {
     772           4 :         struct test_event_fd2_state state;
     773           4 :         int sock[2];
     774           4 :         uint8_t c = 0;
     775             : 
     776           4 :         ZERO_STRUCT(state);
     777           4 :         state.tctx = tctx;
     778           4 :         state.backend = (const char *)test_data;
     779             : 
     780           4 :         state.ev = test_tevent_context_init_byname(tctx, state.backend);
     781           4 :         if (state.ev == NULL) {
     782           0 :                 torture_skip(tctx, talloc_asprintf(tctx,
     783             :                              "event backend '%s' not supported\n",
     784             :                              state.backend));
     785             :                 return true;
     786             :         }
     787             : 
     788           4 :         torture_comment(tctx, "backend '%s' - %s\n",
     789             :                         state.backend, __FUNCTION__);
     790             : 
     791             :         /*
     792             :          * This tests the following
     793             :          *
     794             :          * - We write 1 byte to each socket
     795             :          * - We wait for TEVENT_FD_READ/WRITE on both sockets
     796             :          * - When we get TEVENT_FD_WRITE we write 1 byte
     797             :          *   until both socket buffers are full, which
     798             :          *   means both sockets only get TEVENT_FD_READ.
     799             :          * - Then we read 1 byte until we have consumed
     800             :          *   all bytes the other end has written.
     801             :          */
     802           4 :         sock[0] = -1;
     803           4 :         sock[1] = -1;
     804           4 :         socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
     805             : 
     806             :         /*
     807             :          * the timer should never expire
     808             :          */
     809           4 :         state.te = tevent_add_timer(state.ev, state.ev,
     810             :                                     timeval_current_ofs(600, 0),
     811             :                                     test_event_fd2_finished, &state);
     812           4 :         state.sock0.state = &state;
     813           4 :         state.sock0.fd = sock[0];
     814           4 :         state.sock0.fde = tevent_add_fd(state.ev, state.ev,
     815             :                                         state.sock0.fd,
     816             :                                         TEVENT_FD_READ | TEVENT_FD_WRITE,
     817             :                                         test_event_fd2_sock_handler,
     818             :                                         &state.sock0);
     819           4 :         state.sock1.state = &state;
     820           4 :         state.sock1.fd = sock[1];
     821           4 :         state.sock1.fde = tevent_add_fd(state.ev, state.ev,
     822             :                                         state.sock1.fd,
     823             :                                         TEVENT_FD_READ | TEVENT_FD_WRITE,
     824             :                                         test_event_fd2_sock_handler,
     825             :                                         &state.sock1);
     826             : 
     827           4 :         tevent_fd_set_auto_close(state.sock0.fde);
     828           4 :         tevent_fd_set_auto_close(state.sock1.fde);
     829             : 
     830           4 :         do_write(state.sock0.fd, &c, 1);
     831           4 :         state.sock0.num_written++;
     832           4 :         do_write(state.sock1.fd, &c, 1);
     833           4 :         state.sock1.num_written++;
     834             : 
     835           4 :         while (!state.finished) {
     836        1120 :                 errno = 0;
     837        1120 :                 if (tevent_loop_once(state.ev) == -1) {
     838           0 :                         talloc_free(state.ev);
     839        1124 :                         torture_fail(tctx, talloc_asprintf(tctx,
     840             :                                      "Failed event loop %s\n",
     841             :                                      strerror(errno)));
     842             :                 }
     843             :         }
     844             : 
     845           4 :         talloc_free(state.ev);
     846             : 
     847           4 :         torture_assert(tctx, state.error == NULL, talloc_asprintf(tctx,
     848             :                        "%s", state.error));
     849             : 
     850           0 :         return true;
     851             : }
     852             : 
     853             : struct test_event_fd3_state {
     854             :         struct torture_context *tctx;
     855             :         const char *backend;
     856             :         struct tevent_context *ev;
     857             :         struct timeval start_time;
     858             :         struct tevent_timer *te1, *te2, *te3, *te4, *te5;
     859             :         struct test_event_fd3_sock {
     860             :                 struct test_event_fd3_state *state;
     861             :                 const char *sock_name;
     862             :                 int fd;
     863             :                 const char *phase_name;
     864             :                 uint64_t iteration_id;
     865             :                 uint64_t max_iterations;
     866             :                 uint16_t expected_flags;
     867             :                 uint8_t expected_count;
     868             :                 uint8_t actual_count;
     869             :                 struct test_event_fd3_fde {
     870             :                         struct test_event_fd3_sock *sock;
     871             :                         struct tevent_fd *fde;
     872             :                         uint64_t last_iteration_id;
     873             :                 } fde1, fde2, fde3, fde4, fde5, fde6, fde7, fde8, fde9;
     874             :                 void (*fde_callback)(struct test_event_fd3_fde *tfde,
     875             :                                      uint16_t flags);
     876             :         } sock0, sock1;
     877             :         bool finished;
     878             :         const char *error;
     879             : };
     880             : 
     881       25908 : static void test_event_fd3_fde_callback(struct test_event_fd3_fde *tfde,
     882             :                                         uint16_t flags)
     883             : {
     884       25908 :         struct test_event_fd3_sock *sock = tfde->sock;
     885       25908 :         struct test_event_fd3_state *state = sock->state;
     886       25908 :         uint16_t fde_flags = tevent_fd_get_flags(tfde->fde);
     887       25908 :         uint16_t expected_flags = sock->expected_flags & fde_flags;
     888             : 
     889       25908 :         if (expected_flags == 0) {
     890           0 :                 state->finished = true;
     891           0 :                 state->error = __location__;
     892           0 :                 return;
     893             :         }
     894             : 
     895       25908 :         if (flags != expected_flags) {
     896           0 :                 state->finished = true;
     897           0 :                 state->error = __location__;
     898           0 :                 return;
     899             :         }
     900             : 
     901       25908 :         if (tfde->last_iteration_id == sock->iteration_id) {
     902           0 :                 state->finished = true;
     903           0 :                 state->error = __location__;
     904           0 :                 return;
     905             :         }
     906             : 
     907       25908 :         tfde->last_iteration_id = sock->iteration_id;
     908             : 
     909       25908 :         sock->actual_count += 1;
     910             : 
     911       25908 :         if (sock->actual_count > sock->expected_count) {
     912           0 :                 state->finished = true;
     913           0 :                 state->error = __location__;
     914           0 :                 return;
     915             :         }
     916             : 
     917       25908 :         if (sock->actual_count == sock->expected_count) {
     918        3556 :                 sock->actual_count = 0;
     919        3556 :                 sock->iteration_id += 1;
     920             :         }
     921             : 
     922       25908 :         if (sock->iteration_id > sock->max_iterations) {
     923          28 :                 torture_comment(state->tctx,
     924             :                         "%s: phase[%s] finished with %"PRIu64" iterations\n",
     925             :                         sock->sock_name,
     926             :                         sock->phase_name,
     927             :                         sock->max_iterations);
     928          28 :                 tevent_fd_set_flags(sock->fde1.fde, 0);
     929          28 :                 tevent_fd_set_flags(sock->fde2.fde, 0);
     930          28 :                 tevent_fd_set_flags(sock->fde3.fde, 0);
     931          28 :                 tevent_fd_set_flags(sock->fde4.fde, 0);
     932          28 :                 tevent_fd_set_flags(sock->fde5.fde, 0);
     933          28 :                 tevent_fd_set_flags(sock->fde6.fde, 0);
     934          28 :                 tevent_fd_set_flags(sock->fde7.fde, 0);
     935          28 :                 tevent_fd_set_flags(sock->fde8.fde, 0);
     936          28 :                 tevent_fd_set_flags(sock->fde9.fde, 0);
     937          28 :                 sock->fde_callback = NULL;
     938             :         }
     939             : }
     940             : 
     941          28 : static void test_event_fd3_prepare_phase(struct test_event_fd3_sock *sock,
     942             :                                          const char *phase_name,
     943             :                                          uint64_t max_iterations,
     944             :                                          uint16_t expected_flags,
     945             :                                          uint8_t expected_count,
     946             :                                          uint16_t flags1,
     947             :                                          uint16_t flags2,
     948             :                                          uint16_t flags3,
     949             :                                          uint16_t flags4,
     950             :                                          uint16_t flags5,
     951             :                                          uint16_t flags6,
     952             :                                          uint16_t flags7,
     953             :                                          uint16_t flags8,
     954             :                                          uint16_t flags9)
     955             : {
     956          28 :         struct test_event_fd3_state *state = sock->state;
     957             : 
     958          28 :         if (sock->fde_callback != NULL) {
     959           0 :                 state->finished = true;
     960           0 :                 state->error = __location__;
     961           0 :                 return;
     962             :         }
     963             : 
     964          28 :         sock->phase_name = phase_name;
     965          28 :         sock->max_iterations = max_iterations;
     966          28 :         sock->expected_flags = expected_flags;
     967          28 :         sock->expected_count = expected_count;
     968          28 :         sock->iteration_id = 1;
     969          28 :         sock->actual_count = 0;
     970             : 
     971          28 :         tevent_fd_set_flags(sock->fde1.fde, flags1);
     972          28 :         sock->fde1.last_iteration_id = 0;
     973          28 :         tevent_fd_set_flags(sock->fde2.fde, flags2);
     974          28 :         sock->fde2.last_iteration_id = 0;
     975          28 :         tevent_fd_set_flags(sock->fde3.fde, flags3);
     976          28 :         sock->fde3.last_iteration_id = 0;
     977          28 :         tevent_fd_set_flags(sock->fde4.fde, flags4);
     978          28 :         sock->fde4.last_iteration_id = 0;
     979          28 :         tevent_fd_set_flags(sock->fde5.fde, flags5);
     980          28 :         sock->fde5.last_iteration_id = 0;
     981          28 :         tevent_fd_set_flags(sock->fde6.fde, flags6);
     982          28 :         sock->fde6.last_iteration_id = 0;
     983          28 :         tevent_fd_set_flags(sock->fde7.fde, flags7);
     984          28 :         sock->fde7.last_iteration_id = 0;
     985          28 :         tevent_fd_set_flags(sock->fde8.fde, flags8);
     986          28 :         sock->fde8.last_iteration_id = 0;
     987          28 :         tevent_fd_set_flags(sock->fde9.fde, flags9);
     988          28 :         sock->fde9.last_iteration_id = 0;
     989             : 
     990          28 :         sock->fde_callback = test_event_fd3_fde_callback;
     991             : }
     992             : 
     993       25908 : static void test_event_fd3_sock_handler(struct tevent_context *ev_ctx,
     994             :                                         struct tevent_fd *fde,
     995             :                                         uint16_t flags,
     996             :                                         void *private_data)
     997             : {
     998       25908 :         struct test_event_fd3_fde *tfde =
     999             :                 (struct test_event_fd3_fde *)private_data;
    1000       25908 :         struct test_event_fd3_sock *sock = tfde->sock;
    1001       25908 :         struct test_event_fd3_state *state = sock->state;
    1002             : 
    1003       25908 :         if (sock->fd == -1) {
    1004           0 :                 state->finished = true;
    1005           0 :                 state->error = __location__;
    1006           0 :                 return;
    1007             :         }
    1008             : 
    1009       25908 :         if (sock->fde_callback == NULL) {
    1010           0 :                 state->finished = true;
    1011           0 :                 state->error = __location__;
    1012           0 :                 return;
    1013             :         }
    1014             : 
    1015       25908 :         sock->fde_callback(tfde, flags);
    1016       25908 :         return;
    1017             : }
    1018             : 
    1019          20 : static bool test_event_fd3_assert_timeout(struct test_event_fd3_state *state,
    1020             :                                           double expected_elapsed,
    1021             :                                           const char *func)
    1022             : {
    1023          20 :         double e = timeval_elapsed(&state->start_time);
    1024          20 :         double max_latency = 0.05;
    1025             : 
    1026          20 :         if (e < expected_elapsed) {
    1027           0 :                 torture_comment(state->tctx,
    1028             :                         "%s: elapsed=%.6f < expected_elapsed=%.6f\n",
    1029             :                         func, e, expected_elapsed);
    1030           0 :                 state->finished = true;
    1031           0 :                 state->error = __location__;
    1032           0 :                 return false;
    1033             :         }
    1034             : 
    1035          20 :         if (e > (expected_elapsed + max_latency)) {
    1036           0 :                 torture_comment(state->tctx,
    1037             :                         "%s: elapsed=%.6f > "
    1038             :                         "(expected_elapsed=%.6f + max_latency=%.6f)\n",
    1039             :                         func, e, expected_elapsed, max_latency);
    1040           0 :                 state->finished = true;
    1041           0 :                 state->error = __location__;
    1042           0 :                 return false;
    1043             :         }
    1044             : 
    1045          20 :         torture_comment(state->tctx, "%s: elapsed=%.6f\n", __func__, e);
    1046          20 :         return true;
    1047             : }
    1048             : 
    1049           4 : static void test_event_fd3_writeable(struct tevent_context *ev_ctx,
    1050             :                                     struct tevent_timer *te,
    1051             :                                     struct timeval tval,
    1052             :                                     void *private_data)
    1053             : {
    1054           4 :         struct test_event_fd3_state *state =
    1055             :                 (struct test_event_fd3_state *)private_data;
    1056             : 
    1057           4 :         if (!test_event_fd3_assert_timeout(state, 1, __func__)) {
    1058           0 :                 return;
    1059             :         }
    1060             : 
    1061           4 :         test_event_fd3_prepare_phase(&state->sock0,
    1062             :                 __func__,
    1063             :                 INT8_MAX,
    1064             :                 TEVENT_FD_WRITE,
    1065             :                 5,
    1066             :                 TEVENT_FD_WRITE,
    1067             :                 0,
    1068             :                 TEVENT_FD_READ,
    1069             :                 TEVENT_FD_WRITE,
    1070             :                 TEVENT_FD_READ|TEVENT_FD_WRITE,
    1071             :                 TEVENT_FD_READ,
    1072             :                 TEVENT_FD_WRITE,
    1073             :                 TEVENT_FD_READ|TEVENT_FD_WRITE,
    1074             :                 0);
    1075             : 
    1076           4 :         test_event_fd3_prepare_phase(&state->sock1,
    1077             :                 __func__,
    1078             :                 INT8_MAX,
    1079             :                 TEVENT_FD_WRITE,
    1080             :                 9,
    1081             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1082             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1083             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1084             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1085             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1086             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1087             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1088             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1089             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR);
    1090             : }
    1091             : 
    1092           4 : static void test_event_fd3_readable(struct tevent_context *ev_ctx,
    1093             :                                     struct tevent_timer *te,
    1094             :                                     struct timeval tval,
    1095             :                                     void *private_data)
    1096             : {
    1097           4 :         struct test_event_fd3_state *state =
    1098             :                 (struct test_event_fd3_state *)private_data;
    1099           4 :         uint8_t c = 0;
    1100             : 
    1101           4 :         if (!test_event_fd3_assert_timeout(state, 2, __func__)) {
    1102           0 :                 return;
    1103             :         }
    1104             : 
    1105           4 :         do_write(state->sock0.fd, &c, 1);
    1106           4 :         do_write(state->sock1.fd, &c, 1);
    1107             : 
    1108           4 :         test_event_fd3_prepare_phase(&state->sock0,
    1109             :                 __func__,
    1110             :                 INT8_MAX,
    1111             :                 TEVENT_FD_READ|TEVENT_FD_WRITE,
    1112             :                 9,
    1113             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1114             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1115             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1116             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1117             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1118             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1119             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1120             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1121             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR);
    1122             : 
    1123           4 :         test_event_fd3_prepare_phase(&state->sock1,
    1124             :                 __func__,
    1125             :                 INT8_MAX,
    1126             :                 TEVENT_FD_READ|TEVENT_FD_WRITE,
    1127             :                 7,
    1128             :                 TEVENT_FD_READ,
    1129             :                 TEVENT_FD_READ|TEVENT_FD_WRITE,
    1130             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1131             :                 0,
    1132             :                 TEVENT_FD_READ,
    1133             :                 TEVENT_FD_WRITE,
    1134             :                 TEVENT_FD_ERROR,
    1135             :                 TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1136             :                 TEVENT_FD_READ|TEVENT_FD_WRITE);
    1137             : }
    1138             : 
    1139           4 : static void test_event_fd3_not_writeable(struct tevent_context *ev_ctx,
    1140             :                                          struct tevent_timer *te,
    1141             :                                          struct timeval tval,
    1142             :                                          void *private_data)
    1143             : {
    1144           4 :         struct test_event_fd3_state *state =
    1145             :                 (struct test_event_fd3_state *)private_data;
    1146             : 
    1147           4 :         if (!test_event_fd3_assert_timeout(state, 3, __func__)) {
    1148           0 :                 return;
    1149             :         }
    1150             : 
    1151           4 :         do_fill(state->sock0.fd);
    1152           4 :         do_fill(state->sock1.fd);
    1153             : 
    1154           4 :         test_event_fd3_prepare_phase(&state->sock0,
    1155             :                 __func__,
    1156             :                 INT8_MAX,
    1157             :                 TEVENT_FD_READ,
    1158             :                 5,
    1159             :                 TEVENT_FD_READ|TEVENT_FD_WRITE,
    1160             :                 TEVENT_FD_WRITE,
    1161             :                 TEVENT_FD_READ,
    1162             :                 0,
    1163             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1164             :                 TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1165             :                 TEVENT_FD_READ|TEVENT_FD_ERROR,
    1166             :                 TEVENT_FD_ERROR,
    1167             :                 TEVENT_FD_READ);
    1168             : 
    1169           4 :         test_event_fd3_prepare_phase(&state->sock1,
    1170             :                 __func__,
    1171             :                 INT8_MAX,
    1172             :                 TEVENT_FD_READ,
    1173             :                 9,
    1174             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1175             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1176             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1177             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1178             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1179             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1180             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1181             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1182             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR);
    1183             : }
    1184             : 
    1185           4 : static void test_event_fd3_off(struct tevent_context *ev_ctx,
    1186             :                                     struct tevent_timer *te,
    1187             :                                     struct timeval tval,
    1188             :                                     void *private_data)
    1189             : {
    1190           4 :         struct test_event_fd3_state *state =
    1191             :                 (struct test_event_fd3_state *)private_data;
    1192             : 
    1193           4 :         if (!test_event_fd3_assert_timeout(state, 4, __func__)) {
    1194           0 :                 return;
    1195             :         }
    1196             : 
    1197           4 :         TALLOC_FREE(state->sock0.fde1.fde);
    1198           4 :         state->sock0.fd = -1;
    1199             : 
    1200           4 :         test_event_fd3_prepare_phase(&state->sock1,
    1201             :                 __func__,
    1202             :                 INT8_MAX,
    1203             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1204             :                 7,
    1205             :                 TEVENT_FD_READ|TEVENT_FD_WRITE,
    1206             :                 TEVENT_FD_WRITE,
    1207             :                 TEVENT_FD_READ,
    1208             :                 0,
    1209             :                 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1210             :                 TEVENT_FD_WRITE|TEVENT_FD_ERROR,
    1211             :                 TEVENT_FD_READ|TEVENT_FD_ERROR,
    1212             :                 TEVENT_FD_ERROR,
    1213             :                 TEVENT_FD_READ);
    1214             : }
    1215             : 
    1216           4 : static void test_event_fd3_finished(struct tevent_context *ev_ctx,
    1217             :                                     struct tevent_timer *te,
    1218             :                                     struct timeval tval,
    1219             :                                     void *private_data)
    1220             : {
    1221           4 :         struct test_event_fd3_state *state =
    1222             :                 (struct test_event_fd3_state *)private_data;
    1223             : 
    1224           4 :         if (!test_event_fd3_assert_timeout(state, 5, __func__)) {
    1225           0 :                 return;
    1226             :         }
    1227             : 
    1228             :         /*
    1229             :          * this should never be triggered
    1230             :          */
    1231           4 :         if (state->sock0.fde_callback != NULL) {
    1232           0 :                 state->finished = true;
    1233           0 :                 state->error = __location__;
    1234           0 :                 return;
    1235             :         }
    1236           4 :         if (state->sock1.fde_callback != NULL) {
    1237           0 :                 state->finished = true;
    1238           0 :                 state->error = __location__;
    1239           0 :                 return;
    1240             :         }
    1241             : 
    1242           4 :         state->finished = true;
    1243             : }
    1244             : 
    1245           4 : static bool test_event_fd3(struct torture_context *tctx,
    1246             :                            const void *test_data)
    1247             : {
    1248           4 :         struct test_event_fd3_state state = {
    1249             :                 .tctx = tctx,
    1250             :                 .backend = (const char *)test_data,
    1251             :         };
    1252           4 :         int rc;
    1253           4 :         int sock[2];
    1254             : 
    1255           4 :         state.ev = test_tevent_context_init_byname(tctx, state.backend);
    1256           4 :         if (state.ev == NULL) {
    1257           0 :                 torture_skip(tctx, talloc_asprintf(tctx,
    1258             :                              "event backend '%s' not supported\n",
    1259             :                              state.backend));
    1260             :                 return true;
    1261             :         }
    1262             : 
    1263           4 :         torture_comment(tctx, "backend '%s' - %s\n",
    1264             :                         state.backend, __FUNCTION__);
    1265             : 
    1266           4 :         sock[0] = -1;
    1267           4 :         sock[1] = -1;
    1268           4 :         rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
    1269           4 :         torture_assert_int_equal(tctx, rc, 0, "socketpair()");
    1270             : 
    1271           4 :         state.start_time = timeval_current();
    1272           4 :         state.te1 = tevent_add_timer(state.ev, state.ev,
    1273             :                                      timeval_add(&state.start_time, 5, 0),
    1274             :                                      test_event_fd3_finished, &state);
    1275           4 :         torture_assert(tctx, state.te1 != NULL, "tevent_add_timer()");
    1276           4 :         state.te2 = tevent_add_timer(state.ev, state.ev,
    1277             :                                      timeval_add(&state.start_time, 1, 0),
    1278             :                                      test_event_fd3_writeable, &state);
    1279           4 :         torture_assert(tctx, state.te2 != NULL, "tevent_add_timer()");
    1280           4 :         state.te3 = tevent_add_timer(state.ev, state.ev,
    1281             :                                      timeval_add(&state.start_time, 2, 0),
    1282             :                                      test_event_fd3_readable, &state);
    1283           4 :         torture_assert(tctx, state.te3 != NULL, "tevent_add_timer()");
    1284           4 :         state.te4 = tevent_add_timer(state.ev, state.ev,
    1285             :                                      timeval_add(&state.start_time, 3, 0),
    1286             :                                      test_event_fd3_not_writeable, &state);
    1287           4 :         torture_assert(tctx, state.te4 != NULL, "tevent_add_timer()");
    1288           4 :         state.te5 = tevent_add_timer(state.ev, state.ev,
    1289             :                                      timeval_add(&state.start_time, 4, 0),
    1290             :                                      test_event_fd3_off, &state);
    1291           4 :         torture_assert(tctx, state.te5 != NULL, "tevent_add_timer()");
    1292             : 
    1293           4 :         state.sock0.state = &state;
    1294           4 :         state.sock0.sock_name = "sock0";
    1295           4 :         state.sock0.fd = sock[0];
    1296           4 :         state.sock0.fde1.sock = &state.sock0;
    1297           4 :         state.sock0.fde1.fde = tevent_add_fd(state.ev, state.ev,
    1298             :                                              state.sock0.fd,
    1299             :                                              0,
    1300             :                                              test_event_fd3_sock_handler,
    1301             :                                              &state.sock0.fde1);
    1302           4 :         torture_assert(tctx, state.sock0.fde1.fde != NULL, "tevent_add_fd()");
    1303           4 :         tevent_fd_set_auto_close(state.sock0.fde1.fde);
    1304           4 :         state.sock0.fde2.sock = &state.sock0;
    1305           4 :         state.sock0.fde2.fde = tevent_add_fd(state.ev, state.ev,
    1306             :                                              state.sock0.fd,
    1307             :                                              0,
    1308             :                                              test_event_fd3_sock_handler,
    1309             :                                              &state.sock0.fde2);
    1310           4 :         torture_assert(tctx, state.sock0.fde2.fde != NULL, "tevent_add_fd()");
    1311           4 :         state.sock0.fde3.sock = &state.sock0;
    1312           4 :         state.sock0.fde3.fde = tevent_add_fd(state.ev, state.ev,
    1313             :                                              state.sock0.fd,
    1314             :                                              0,
    1315             :                                              test_event_fd3_sock_handler,
    1316             :                                              &state.sock0.fde3);
    1317           4 :         torture_assert(tctx, state.sock0.fde3.fde != NULL, "tevent_add_fd()");
    1318           4 :         state.sock0.fde4.sock = &state.sock0;
    1319           4 :         state.sock0.fde4.fde = tevent_add_fd(state.ev, state.ev,
    1320             :                                              state.sock0.fd,
    1321             :                                              0,
    1322             :                                              test_event_fd3_sock_handler,
    1323             :                                              &state.sock0.fde4);
    1324           4 :         torture_assert(tctx, state.sock0.fde4.fde != NULL, "tevent_add_fd()");
    1325           4 :         state.sock0.fde5.sock = &state.sock0;
    1326           4 :         state.sock0.fde5.fde = tevent_add_fd(state.ev, state.ev,
    1327             :                                              state.sock0.fd,
    1328             :                                              0,
    1329             :                                              test_event_fd3_sock_handler,
    1330             :                                              &state.sock0.fde5);
    1331           4 :         torture_assert(tctx, state.sock0.fde5.fde != NULL, "tevent_add_fd()");
    1332           4 :         state.sock0.fde6.sock = &state.sock0;
    1333           4 :         state.sock0.fde6.fde = tevent_add_fd(state.ev, state.ev,
    1334             :                                              state.sock0.fd,
    1335             :                                              0,
    1336             :                                              test_event_fd3_sock_handler,
    1337             :                                              &state.sock0.fde6);
    1338           4 :         torture_assert(tctx, state.sock0.fde6.fde != NULL, "tevent_add_fd()");
    1339           4 :         state.sock0.fde7.sock = &state.sock0;
    1340           4 :         state.sock0.fde7.fde = tevent_add_fd(state.ev, state.ev,
    1341             :                                              state.sock0.fd,
    1342             :                                              0,
    1343             :                                              test_event_fd3_sock_handler,
    1344             :                                              &state.sock0.fde7);
    1345           4 :         torture_assert(tctx, state.sock0.fde7.fde != NULL, "tevent_add_fd()");
    1346           4 :         state.sock0.fde8.sock = &state.sock0;
    1347           4 :         state.sock0.fde8.fde = tevent_add_fd(state.ev, state.ev,
    1348             :                                              state.sock0.fd,
    1349             :                                              0,
    1350             :                                              test_event_fd3_sock_handler,
    1351             :                                              &state.sock0.fde8);
    1352           4 :         torture_assert(tctx, state.sock0.fde8.fde != NULL, "tevent_add_fd()");
    1353           4 :         state.sock0.fde9.sock = &state.sock0;
    1354           4 :         state.sock0.fde9.fde = tevent_add_fd(state.ev, state.ev,
    1355             :                                              state.sock0.fd,
    1356             :                                              0,
    1357             :                                              test_event_fd3_sock_handler,
    1358             :                                              &state.sock0.fde9);
    1359           4 :         torture_assert(tctx, state.sock0.fde9.fde != NULL, "tevent_add_fd()");
    1360             : 
    1361           4 :         state.sock1.state = &state;
    1362           4 :         state.sock1.sock_name = "sock1";
    1363           4 :         state.sock1.fd = sock[1];
    1364           4 :         state.sock1.fde1.sock = &state.sock1;
    1365           4 :         state.sock1.fde1.fde = tevent_add_fd(state.ev, state.ev,
    1366             :                                              state.sock1.fd,
    1367             :                                              1,
    1368             :                                              test_event_fd3_sock_handler,
    1369             :                                              &state.sock1.fde1);
    1370           4 :         torture_assert(tctx, state.sock1.fde1.fde != NULL, "tevent_add_fd()");
    1371           4 :         tevent_fd_set_auto_close(state.sock1.fde1.fde);
    1372           4 :         state.sock1.fde2.sock = &state.sock1;
    1373           4 :         state.sock1.fde2.fde = tevent_add_fd(state.ev, state.ev,
    1374             :                                              state.sock1.fd,
    1375             :                                              0,
    1376             :                                              test_event_fd3_sock_handler,
    1377             :                                              &state.sock1.fde2);
    1378           4 :         torture_assert(tctx, state.sock1.fde2.fde != NULL, "tevent_add_fd()");
    1379           4 :         state.sock1.fde3.sock = &state.sock1;
    1380           4 :         state.sock1.fde3.fde = tevent_add_fd(state.ev, state.ev,
    1381             :                                              state.sock1.fd,
    1382             :                                              0,
    1383             :                                              test_event_fd3_sock_handler,
    1384             :                                              &state.sock1.fde3);
    1385           4 :         torture_assert(tctx, state.sock1.fde3.fde != NULL, "tevent_add_fd()");
    1386           4 :         state.sock1.fde4.sock = &state.sock1;
    1387           4 :         state.sock1.fde4.fde = tevent_add_fd(state.ev, state.ev,
    1388             :                                              state.sock1.fd,
    1389             :                                              0,
    1390             :                                              test_event_fd3_sock_handler,
    1391             :                                              &state.sock1.fde4);
    1392           4 :         torture_assert(tctx, state.sock1.fde4.fde != NULL, "tevent_add_fd()");
    1393           4 :         state.sock1.fde5.sock = &state.sock1;
    1394           4 :         state.sock1.fde5.fde = tevent_add_fd(state.ev, state.ev,
    1395             :                                              state.sock1.fd,
    1396             :                                              0,
    1397             :                                              test_event_fd3_sock_handler,
    1398             :                                              &state.sock1.fde5);
    1399           4 :         torture_assert(tctx, state.sock1.fde5.fde != NULL, "tevent_add_fd()");
    1400           4 :         state.sock1.fde6.sock = &state.sock1;
    1401           4 :         state.sock1.fde6.fde = tevent_add_fd(state.ev, state.ev,
    1402             :                                              state.sock1.fd,
    1403             :                                              0,
    1404             :                                              test_event_fd3_sock_handler,
    1405             :                                              &state.sock1.fde6);
    1406           4 :         torture_assert(tctx, state.sock1.fde6.fde != NULL, "tevent_add_fd()");
    1407           4 :         state.sock1.fde7.sock = &state.sock1;
    1408           4 :         state.sock1.fde7.fde = tevent_add_fd(state.ev, state.ev,
    1409             :                                              state.sock1.fd,
    1410             :                                              0,
    1411             :                                              test_event_fd3_sock_handler,
    1412             :                                              &state.sock1.fde7);
    1413           4 :         torture_assert(tctx, state.sock1.fde7.fde != NULL, "tevent_add_fd()");
    1414           4 :         state.sock1.fde8.sock = &state.sock1;
    1415           4 :         state.sock1.fde8.fde = tevent_add_fd(state.ev, state.ev,
    1416             :                                              state.sock1.fd,
    1417             :                                              0,
    1418             :                                              test_event_fd3_sock_handler,
    1419             :                                              &state.sock1.fde8);
    1420           4 :         torture_assert(tctx, state.sock1.fde8.fde != NULL, "tevent_add_fd()");
    1421           4 :         state.sock1.fde9.sock = &state.sock1;
    1422           4 :         state.sock1.fde9.fde = tevent_add_fd(state.ev, state.ev,
    1423             :                                              state.sock1.fd,
    1424             :                                              0,
    1425             :                                              test_event_fd3_sock_handler,
    1426             :                                              &state.sock1.fde9);
    1427           4 :         torture_assert(tctx, state.sock1.fde9.fde != NULL, "tevent_add_fd()");
    1428             : 
    1429       25944 :         while (!state.finished) {
    1430       25940 :                 errno = 0;
    1431       25940 :                 if (tevent_loop_once(state.ev) == -1) {
    1432           0 :                         talloc_free(state.ev);
    1433       25944 :                         torture_fail(tctx, talloc_asprintf(tctx,
    1434             :                                      "Failed event loop %s\n",
    1435             :                                      strerror(errno)));
    1436             :                 }
    1437             :         }
    1438             : 
    1439           4 :         talloc_free(state.ev);
    1440             : 
    1441           4 :         torture_assert(tctx, state.error == NULL, talloc_asprintf(tctx,
    1442             :                        "%s", state.error));
    1443             : 
    1444           0 :         return true;
    1445             : }
    1446             : 
    1447             : struct test_wrapper_state {
    1448             :         struct torture_context *tctx;
    1449             :         int num_events;
    1450             :         int num_wrap_handlers;
    1451             : };
    1452             : 
    1453           4 : static bool test_wrapper_before_use(struct tevent_context *wrap_ev,
    1454             :                                     void *private_data,
    1455             :                                     struct tevent_context *main_ev,
    1456             :                                     const char *location)
    1457             : {
    1458           4 :         struct test_wrapper_state *state =
    1459           4 :                 talloc_get_type_abort(private_data,
    1460             :                 struct test_wrapper_state);
    1461             : 
    1462           4 :         torture_comment(state->tctx, "%s\n", __func__);
    1463           4 :         state->num_wrap_handlers++;
    1464           4 :         return true;
    1465             : }
    1466             : 
    1467           4 : static void test_wrapper_after_use(struct tevent_context *wrap_ev,
    1468             :                                    void *private_data,
    1469             :                                    struct tevent_context *main_ev,
    1470             :                                    const char *location)
    1471             : {
    1472           4 :         struct test_wrapper_state *state =
    1473           4 :                 talloc_get_type_abort(private_data,
    1474             :                 struct test_wrapper_state);
    1475             : 
    1476           4 :         torture_comment(state->tctx, "%s\n", __func__);
    1477           4 :         state->num_wrap_handlers++;
    1478           4 : }
    1479             : 
    1480           4 : static void test_wrapper_before_fd_handler(struct tevent_context *wrap_ev,
    1481             :                                            void *private_data,
    1482             :                                            struct tevent_context *main_ev,
    1483             :                                            struct tevent_fd *fde,
    1484             :                                            uint16_t flags,
    1485             :                                            const char *handler_name,
    1486             :                                            const char *location)
    1487             : {
    1488           4 :         struct test_wrapper_state *state =
    1489           4 :                 talloc_get_type_abort(private_data,
    1490             :                 struct test_wrapper_state);
    1491             : 
    1492           4 :         torture_comment(state->tctx, "%s\n", __func__);
    1493           4 :         state->num_wrap_handlers++;
    1494           4 : }
    1495             : 
    1496           4 : static void test_wrapper_after_fd_handler(struct tevent_context *wrap_ev,
    1497             :                                           void *private_data,
    1498             :                                           struct tevent_context *main_ev,
    1499             :                                           struct tevent_fd *fde,
    1500             :                                           uint16_t flags,
    1501             :                                           const char *handler_name,
    1502             :                                           const char *location)
    1503             : {
    1504           4 :         struct test_wrapper_state *state =
    1505           4 :                 talloc_get_type_abort(private_data,
    1506             :                 struct test_wrapper_state);
    1507             : 
    1508           4 :         torture_comment(state->tctx, "%s\n", __func__);
    1509           4 :         state->num_wrap_handlers++;
    1510           4 : }
    1511             : 
    1512           4 : static void test_wrapper_before_timer_handler(struct tevent_context *wrap_ev,
    1513             :                                               void *private_data,
    1514             :                                               struct tevent_context *main_ev,
    1515             :                                               struct tevent_timer *te,
    1516             :                                               struct timeval requested_time,
    1517             :                                               struct timeval trigger_time,
    1518             :                                               const char *handler_name,
    1519             :                                               const char *location)
    1520             : {
    1521           4 :         struct test_wrapper_state *state =
    1522           4 :                 talloc_get_type_abort(private_data,
    1523             :                 struct test_wrapper_state);
    1524             : 
    1525           4 :         torture_comment(state->tctx, "%s\n", __func__);
    1526           4 :         state->num_wrap_handlers++;
    1527           4 : }
    1528             : 
    1529           4 : static void test_wrapper_after_timer_handler(struct tevent_context *wrap_ev,
    1530             :                                              void *private_data,
    1531             :                                              struct tevent_context *main_ev,
    1532             :                                              struct tevent_timer *te,
    1533             :                                              struct timeval requested_time,
    1534             :                                              struct timeval trigger_time,
    1535             :                                              const char *handler_name,
    1536             :                                              const char *location)
    1537             : {
    1538           4 :         struct test_wrapper_state *state =
    1539           4 :                 talloc_get_type_abort(private_data,
    1540             :                 struct test_wrapper_state);
    1541             : 
    1542           4 :         torture_comment(state->tctx, "%s\n", __func__);
    1543           4 :         state->num_wrap_handlers++;
    1544           4 : }
    1545             : 
    1546           4 : static void test_wrapper_before_immediate_handler(struct tevent_context *wrap_ev,
    1547             :                                                   void *private_data,
    1548             :                                                   struct tevent_context *main_ev,
    1549             :                                                   struct tevent_immediate *im,
    1550             :                                                   const char *handler_name,
    1551             :                                                   const char *location)
    1552             : {
    1553           4 :         struct test_wrapper_state *state =
    1554           4 :                 talloc_get_type_abort(private_data,
    1555             :                 struct test_wrapper_state);
    1556             : 
    1557           4 :         torture_comment(state->tctx, "%s\n", __func__);
    1558           4 :         state->num_wrap_handlers++;
    1559           4 : }
    1560             : 
    1561           4 : static void test_wrapper_after_immediate_handler(struct tevent_context *wrap_ev,
    1562             :                                                  void *private_data,
    1563             :                                                  struct tevent_context *main_ev,
    1564             :                                                  struct tevent_immediate *im,
    1565             :                                                  const char *handler_name,
    1566             :                                                  const char *location)
    1567             : {
    1568           4 :         struct test_wrapper_state *state =
    1569           4 :                 talloc_get_type_abort(private_data,
    1570             :                 struct test_wrapper_state);
    1571             : 
    1572           4 :         torture_comment(state->tctx, "%s\n", __func__);
    1573           4 :         state->num_wrap_handlers++;
    1574           4 : }
    1575             : 
    1576           8 : static void test_wrapper_before_signal_handler(struct tevent_context *wrap_ev,
    1577             :                                                void *private_data,
    1578             :                                                struct tevent_context *main_ev,
    1579             :                                                struct tevent_signal *se,
    1580             :                                                int signum,
    1581             :                                                int count,
    1582             :                                                void *siginfo,
    1583             :                                                const char *handler_name,
    1584             :                                                const char *location)
    1585             : {
    1586           8 :         struct test_wrapper_state *state =
    1587           8 :                 talloc_get_type_abort(private_data,
    1588             :                 struct test_wrapper_state);
    1589             : 
    1590           8 :         torture_comment(state->tctx, "%s\n", __func__);
    1591           8 :         state->num_wrap_handlers++;
    1592           8 : }
    1593             : 
    1594           8 : static void test_wrapper_after_signal_handler(struct tevent_context *wrap_ev,
    1595             :                                               void *private_data,
    1596             :                                               struct tevent_context *main_ev,
    1597             :                                               struct tevent_signal *se,
    1598             :                                               int signum,
    1599             :                                               int count,
    1600             :                                               void *siginfo,
    1601             :                                               const char *handler_name,
    1602             :                                               const char *location)
    1603             : {
    1604           8 :         struct test_wrapper_state *state =
    1605           8 :                 talloc_get_type_abort(private_data,
    1606             :                 struct test_wrapper_state);
    1607             : 
    1608           8 :         torture_comment(state->tctx, "%s\n", __func__);
    1609           8 :         state->num_wrap_handlers++;
    1610           8 : }
    1611             : 
    1612             : static const struct tevent_wrapper_ops test_wrapper_ops = {
    1613             :         .name                           = "test_wrapper",
    1614             :         .before_use                     = test_wrapper_before_use,
    1615             :         .after_use                      = test_wrapper_after_use,
    1616             :         .before_fd_handler              = test_wrapper_before_fd_handler,
    1617             :         .after_fd_handler               = test_wrapper_after_fd_handler,
    1618             :         .before_timer_handler           = test_wrapper_before_timer_handler,
    1619             :         .after_timer_handler            = test_wrapper_after_timer_handler,
    1620             :         .before_immediate_handler       = test_wrapper_before_immediate_handler,
    1621             :         .after_immediate_handler        = test_wrapper_after_immediate_handler,
    1622             :         .before_signal_handler          = test_wrapper_before_signal_handler,
    1623             :         .after_signal_handler           = test_wrapper_after_signal_handler,
    1624             : };
    1625             : 
    1626           4 : static void test_wrapper_timer_handler(struct tevent_context *ev,
    1627             :                                        struct tevent_timer *te,
    1628             :                                        struct timeval tv,
    1629             :                                        void *private_data)
    1630             : {
    1631           4 :         struct test_wrapper_state *state =
    1632             :                 (struct test_wrapper_state *)private_data;
    1633             : 
    1634             : 
    1635           4 :         torture_comment(state->tctx, "timer handler\n");
    1636             : 
    1637           4 :         state->num_events++;
    1638           4 :         talloc_free(te);
    1639           4 :         return;
    1640             : }
    1641             : 
    1642           4 : static void test_wrapper_fd_handler(struct tevent_context *ev,
    1643             :                                     struct tevent_fd *fde,
    1644             :                                     unsigned short fd_flags,
    1645             :                                     void *private_data)
    1646             : {
    1647           4 :         struct test_wrapper_state *state =
    1648             :                 (struct test_wrapper_state *)private_data;
    1649             : 
    1650           4 :         torture_comment(state->tctx, "fd handler\n");
    1651             : 
    1652           4 :         state->num_events++;
    1653           4 :         talloc_free(fde);
    1654           4 :         return;
    1655             : }
    1656             : 
    1657           4 : static void test_wrapper_immediate_handler(struct tevent_context *ev,
    1658             :                                            struct tevent_immediate *im,
    1659             :                                            void *private_data)
    1660             : {
    1661           4 :         struct test_wrapper_state *state =
    1662             :                 (struct test_wrapper_state *)private_data;
    1663             : 
    1664           4 :         state->num_events++;
    1665           4 :         talloc_free(im);
    1666             : 
    1667           4 :         torture_comment(state->tctx, "immediate handler\n");
    1668           4 :         return;
    1669             : }
    1670             : 
    1671           4 : static void test_wrapper_signal_handler(struct tevent_context *ev,
    1672             :                                         struct tevent_signal *se,
    1673             :                                         int signum,
    1674             :                                         int count,
    1675             :                                         void *siginfo,
    1676             :                                         void *private_data)
    1677             : {
    1678           4 :         struct test_wrapper_state *state =
    1679             :                 (struct test_wrapper_state *)private_data;
    1680             : 
    1681           4 :         torture_comment(state->tctx, "signal handler\n");
    1682             : 
    1683           4 :         state->num_events++;
    1684           4 :         talloc_free(se);
    1685           4 :         return;
    1686             : }
    1687             : 
    1688           4 : static bool test_wrapper(struct torture_context *tctx,
    1689             :                          const void *test_data)
    1690             : {
    1691           4 :         struct test_wrapper_state *state = NULL;
    1692           4 :         int sock[2] = { -1, -1};
    1693           4 :         uint8_t c = 0;
    1694           4 :         const int num_events = 4;
    1695           4 :         const char *backend = (const char *)test_data;
    1696           4 :         struct tevent_context *ev = NULL;
    1697           4 :         struct tevent_context *wrap_ev = NULL;
    1698           4 :         struct tevent_fd *fde = NULL;
    1699           4 :         struct tevent_timer *te = NULL;
    1700           4 :         struct tevent_signal *se = NULL;
    1701           4 :         struct tevent_immediate *im = NULL;
    1702           4 :         int ret;
    1703           4 :         bool ok = false;
    1704           4 :         bool ret2;
    1705             : 
    1706           4 :         ev = test_tevent_context_init_byname(tctx, backend);
    1707           4 :         if (ev == NULL) {
    1708           0 :                 torture_skip(tctx, talloc_asprintf(tctx,
    1709             :                              "event backend '%s' not supported\n",
    1710             :                              backend));
    1711             :                 return true;
    1712             :         }
    1713             : 
    1714           4 :         torture_comment(tctx, "tevent backend '%s'\n", backend);
    1715             : 
    1716           4 :         wrap_ev = tevent_context_wrapper_create(
    1717             :                 ev, ev, &test_wrapper_ops, &state, struct test_wrapper_state);
    1718           4 :         torture_assert_not_null_goto(tctx, wrap_ev, ok, done,
    1719             :                                      "tevent_context_wrapper_create failed\n");
    1720           4 :         *state = (struct test_wrapper_state) {
    1721             :                 .tctx = tctx,
    1722             :         };
    1723             : 
    1724           4 :         ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
    1725           4 :         torture_assert_goto(tctx, ret == 0, ok, done, "socketpair failed\n");
    1726             : 
    1727           4 :         te = tevent_add_timer(wrap_ev, wrap_ev,
    1728             :                               timeval_current_ofs(0, 0),
    1729             :                               test_wrapper_timer_handler, state);
    1730           4 :         torture_assert_not_null_goto(tctx, te, ok, done,
    1731             :                                      "tevent_add_timer failed\n");
    1732             : 
    1733           4 :         fde = tevent_add_fd(wrap_ev, wrap_ev,
    1734             :                             sock[1],
    1735             :                             TEVENT_FD_READ,
    1736             :                             test_wrapper_fd_handler,
    1737             :                             state);
    1738           4 :         torture_assert_not_null_goto(tctx, fde, ok, done,
    1739             :                                      "tevent_add_fd failed\n");
    1740             : 
    1741           4 :         im = tevent_create_immediate(wrap_ev);
    1742           4 :         torture_assert_not_null_goto(tctx, im, ok, done,
    1743             :                                      "tevent_create_immediate failed\n");
    1744             : 
    1745           4 :         se = tevent_add_signal(wrap_ev, wrap_ev,
    1746             :                                SIGUSR1,
    1747             :                                0,
    1748             :                                test_wrapper_signal_handler,
    1749             :                                state);
    1750           4 :         torture_assert_not_null_goto(tctx, se, ok, done,
    1751             :                                      "tevent_add_signal failed\n");
    1752             : 
    1753           4 :         do_write(sock[0], &c, 1);
    1754           4 :         kill(getpid(), SIGUSR1);
    1755           4 :         tevent_schedule_immediate(im,
    1756             :                                   wrap_ev,
    1757             :                                   test_wrapper_immediate_handler,
    1758           4 :                                   state);
    1759             : 
    1760           4 :         ret2 = tevent_context_push_use(wrap_ev);
    1761           4 :         torture_assert_goto(tctx, ret2, ok, done, "tevent_context_push_use(wrap_ev) failed\n");
    1762           4 :         ret2 = tevent_context_push_use(ev);
    1763           4 :         torture_assert_goto(tctx, ret2, ok, pop_use, "tevent_context_push_use(ev) failed\n");
    1764           4 :         tevent_context_pop_use(ev);
    1765           4 :         tevent_context_pop_use(wrap_ev);
    1766             : 
    1767           4 :         ret = tevent_loop_wait(ev);
    1768           4 :         torture_assert_int_equal_goto(tctx, ret, 0, ok, done, "tevent_loop_wait failed\n");
    1769             : 
    1770           4 :         torture_comment(tctx, "Num events: %d\n", state->num_events);
    1771           4 :         torture_comment(tctx, "Num wrap handlers: %d\n",
    1772           4 :                         state->num_wrap_handlers);
    1773             : 
    1774           4 :         torture_assert_int_equal_goto(tctx, state->num_events, num_events, ok, done,
    1775             :                                       "Wrong event count\n");
    1776           4 :         torture_assert_int_equal_goto(tctx, state->num_wrap_handlers,
    1777             :                                       num_events*2+2,
    1778             :                                       ok, done, "Wrong wrapper count\n");
    1779             : 
    1780           0 :         ok = true;
    1781             : 
    1782           4 : done:
    1783           4 :         TALLOC_FREE(wrap_ev);
    1784           4 :         TALLOC_FREE(ev);
    1785             : 
    1786           4 :         if (sock[0] != -1) {
    1787           4 :                 close(sock[0]);
    1788             :         }
    1789           4 :         if (sock[1] != -1) {
    1790           4 :                 close(sock[1]);
    1791             :         }
    1792           0 :         return ok;
    1793           0 : pop_use:
    1794           0 :         tevent_context_pop_use(wrap_ev);
    1795           0 :         goto done;
    1796             : }
    1797             : 
    1798           4 : static void test_free_wrapper_signal_handler(struct tevent_context *ev,
    1799             :                                         struct tevent_signal *se,
    1800             :                                         int signum,
    1801             :                                         int count,
    1802             :                                         void *siginfo,
    1803             :                                         void *private_data)
    1804             : {
    1805           4 :         struct torture_context *tctx =
    1806           4 :                 talloc_get_type_abort(private_data,
    1807             :                 struct torture_context);
    1808             : 
    1809           4 :         torture_comment(tctx, "signal handler\n");
    1810             : 
    1811           4 :         talloc_free(se);
    1812             : 
    1813             :         /*
    1814             :          * signal handlers have highest priority in tevent, so this signal
    1815             :          * handler will always be started before the other handlers
    1816             :          * below. Freeing the (wrapper) event context here tests that the
    1817             :          * wrapper implementation correctly handles the wrapper ev going away
    1818             :          * with pending events.
    1819             :          */
    1820           4 :         talloc_free(ev);
    1821           4 :         return;
    1822             : }
    1823             : 
    1824           0 : static void test_free_wrapper_fd_handler(struct tevent_context *ev,
    1825             :                                          struct tevent_fd *fde,
    1826             :                                          unsigned short fd_flags,
    1827             :                                          void *private_data)
    1828             : {
    1829             :         /*
    1830             :          * This should never be called as
    1831             :          * test_free_wrapper_signal_handler()
    1832             :          * already destroyed the wrapper tevent_context.
    1833             :          */
    1834           0 :         abort();
    1835             : }
    1836             : 
    1837           0 : static void test_free_wrapper_immediate_handler(struct tevent_context *ev,
    1838             :                                            struct tevent_immediate *im,
    1839             :                                            void *private_data)
    1840             : {
    1841             :         /*
    1842             :          * This should never be called as
    1843             :          * test_free_wrapper_signal_handler()
    1844             :          * already destroyed the wrapper tevent_context.
    1845             :          */
    1846           0 :         abort();
    1847             : }
    1848             : 
    1849           0 : static void test_free_wrapper_timer_handler(struct tevent_context *ev,
    1850             :                                        struct tevent_timer *te,
    1851             :                                        struct timeval tv,
    1852             :                                        void *private_data)
    1853             : {
    1854             :         /*
    1855             :          * This should never be called as
    1856             :          * test_free_wrapper_signal_handler()
    1857             :          * already destroyed the wrapper tevent_context.
    1858             :          */
    1859           0 :         abort();
    1860             : }
    1861             : 
    1862           4 : static bool test_free_wrapper(struct torture_context *tctx,
    1863             :                               const void *test_data)
    1864             : {
    1865           4 :         struct test_wrapper_state *state = NULL;
    1866           4 :         int sock[2] = { -1, -1};
    1867           4 :         uint8_t c = 0;
    1868           4 :         const char *backend = (const char *)test_data;
    1869           4 :         TALLOC_CTX *frame = talloc_stackframe();
    1870           4 :         struct tevent_context *ev = NULL;
    1871           4 :         struct tevent_context *wrap_ev = NULL;
    1872           4 :         struct tevent_fd *fde = NULL;
    1873           4 :         struct tevent_timer *te = NULL;
    1874           4 :         struct tevent_signal *se = NULL;
    1875           4 :         struct tevent_immediate *im = NULL;
    1876           4 :         int ret;
    1877           4 :         bool ok = false;
    1878             : 
    1879           4 :         ev = test_tevent_context_init_byname(frame, backend);
    1880           4 :         if (ev == NULL) {
    1881           0 :                 torture_skip(tctx, talloc_asprintf(tctx,
    1882             :                              "event backend '%s' not supported\n",
    1883             :                              backend));
    1884             :                 return true;
    1885             :         }
    1886             : 
    1887           4 :         torture_comment(tctx, "tevent backend '%s'\n", backend);
    1888             : 
    1889           4 :         wrap_ev = tevent_context_wrapper_create(
    1890             :                 ev, ev, &test_wrapper_ops, &state, struct test_wrapper_state);
    1891           4 :         torture_assert_not_null_goto(tctx, wrap_ev, ok, done,
    1892             :                                      "tevent_context_wrapper_create failed\n");
    1893           4 :         *state = (struct test_wrapper_state) {
    1894             :                 .tctx = tctx,
    1895             :         };
    1896             : 
    1897           4 :         ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
    1898           4 :         torture_assert_goto(tctx, ret == 0, ok, done, "socketpair failed\n");
    1899             : 
    1900           4 :         fde = tevent_add_fd(wrap_ev, frame,
    1901             :                             sock[1],
    1902             :                             TEVENT_FD_READ,
    1903             :                             test_free_wrapper_fd_handler,
    1904             :                             NULL);
    1905           4 :         torture_assert_not_null_goto(tctx, fde, ok, done,
    1906             :                                      "tevent_add_fd failed\n");
    1907             : 
    1908           4 :         te = tevent_add_timer(wrap_ev, frame,
    1909             :                               timeval_current_ofs(0, 0),
    1910             :                               test_free_wrapper_timer_handler, NULL);
    1911           4 :         torture_assert_not_null_goto(tctx, te, ok, done,
    1912             :                                      "tevent_add_timer failed\n");
    1913             : 
    1914           4 :         im = tevent_create_immediate(frame);
    1915           4 :         torture_assert_not_null_goto(tctx, im, ok, done,
    1916             :                                      "tevent_create_immediate failed\n");
    1917             : 
    1918           4 :         se = tevent_add_signal(wrap_ev, frame,
    1919             :                                SIGUSR1,
    1920             :                                0,
    1921             :                                test_free_wrapper_signal_handler,
    1922             :                                tctx);
    1923           4 :         torture_assert_not_null_goto(tctx, se, ok, done,
    1924             :                                      "tevent_add_signal failed\n");
    1925             : 
    1926           4 :         do_write(sock[0], &c, 1);
    1927           4 :         kill(getpid(), SIGUSR1);
    1928           4 :         tevent_schedule_immediate(im,
    1929             :                                   wrap_ev,
    1930             :                                   test_free_wrapper_immediate_handler,
    1931           4 :                                   NULL);
    1932             : 
    1933           4 :         ret = tevent_loop_wait(ev);
    1934           4 :         torture_assert_goto(tctx, ret == 0, ok, done, "tevent_loop_wait failed\n");
    1935             : 
    1936           0 :         ok = true;
    1937             : 
    1938           4 : done:
    1939           4 :         TALLOC_FREE(frame);
    1940             : 
    1941           4 :         if (sock[0] != -1) {
    1942           4 :                 close(sock[0]);
    1943             :         }
    1944           4 :         if (sock[1] != -1) {
    1945           4 :                 close(sock[1]);
    1946             :         }
    1947           0 :         return ok;
    1948             : }
    1949             : 
    1950             : #ifdef HAVE_PTHREAD
    1951             : 
    1952             : static pthread_mutex_t threaded_mutex = PTHREAD_MUTEX_INITIALIZER;
    1953             : static bool do_shutdown = false;
    1954             : 
    1955           6 : static void test_event_threaded_lock(void)
    1956             : {
    1957           6 :         int ret;
    1958           6 :         ret = pthread_mutex_lock(&threaded_mutex);
    1959           6 :         assert(ret == 0);
    1960           6 : }
    1961             : 
    1962           6 : static void test_event_threaded_unlock(void)
    1963             : {
    1964           6 :         int ret;
    1965           6 :         ret = pthread_mutex_unlock(&threaded_mutex);
    1966           6 :         assert(ret == 0);
    1967           6 : }
    1968             : 
    1969          12 : static void test_event_threaded_trace(enum tevent_trace_point point,
    1970             :                                       void *private_data)
    1971             : {
    1972          12 :         switch (point) {
    1973           3 :         case TEVENT_TRACE_BEFORE_WAIT:
    1974           3 :                 test_event_threaded_unlock();
    1975           3 :                 break;
    1976           3 :         case TEVENT_TRACE_AFTER_WAIT:
    1977           3 :                 test_event_threaded_lock();
    1978           3 :                 break;
    1979           0 :         case TEVENT_TRACE_BEFORE_LOOP_ONCE:
    1980             :         case TEVENT_TRACE_AFTER_LOOP_ONCE:
    1981           0 :                 break;
    1982             :         }
    1983          12 : }
    1984             : 
    1985           0 : static void test_event_threaded_timer(struct tevent_context *ev,
    1986             :                                       struct tevent_timer *te,
    1987             :                                       struct timeval current_time,
    1988             :                                       void *private_data)
    1989             : {
    1990           0 :         return;
    1991             : }
    1992             : 
    1993           1 : static void *test_event_poll_thread(void *private_data)
    1994             : {
    1995           1 :         struct tevent_context *ev = (struct tevent_context *)private_data;
    1996             : 
    1997           1 :         test_event_threaded_lock();
    1998             : 
    1999           3 :         while (true) {
    2000           3 :                 int ret;
    2001           3 :                 ret = tevent_loop_once(ev);
    2002           3 :                 assert(ret == 0);
    2003           3 :                 if (do_shutdown) {
    2004           1 :                         test_event_threaded_unlock();
    2005           1 :                         return NULL;
    2006             :                 }
    2007             :         }
    2008             : 
    2009             : }
    2010             : 
    2011           2 : static void test_event_threaded_read_handler(struct tevent_context *ev,
    2012             :                                              struct tevent_fd *fde,
    2013             :                                              uint16_t flags,
    2014             :                                              void *private_data)
    2015             : {
    2016           2 :         int *pfd = (int *)private_data;
    2017           2 :         char c;
    2018           2 :         ssize_t nread;
    2019             : 
    2020           2 :         if ((flags & TEVENT_FD_READ) == 0) {
    2021           0 :                 return;
    2022             :         }
    2023             : 
    2024           2 :         do {
    2025           2 :                 nread = read(*pfd, &c, 1);
    2026           2 :         } while ((nread == -1) && (errno == EINTR));
    2027             : 
    2028           2 :         assert(nread == 1);
    2029             : }
    2030             : 
    2031           1 : static bool test_event_context_threaded(struct torture_context *test,
    2032             :                                         const void *test_data)
    2033             : {
    2034           1 :         struct tevent_context *ev;
    2035           1 :         struct tevent_timer *te;
    2036           1 :         struct tevent_fd *fde;
    2037           1 :         pthread_t poll_thread;
    2038           1 :         int fds[2];
    2039           1 :         int ret;
    2040           1 :         char c = 0;
    2041             : 
    2042           1 :         ev = test_tevent_context_init_byname(test, "poll_mt");
    2043           1 :         torture_assert(test, ev != NULL, "poll_mt not supported");
    2044             : 
    2045           1 :         tevent_set_trace_callback(ev, test_event_threaded_trace, NULL);
    2046             : 
    2047           1 :         te = tevent_add_timer(ev, ev, timeval_current_ofs(5, 0),
    2048             :                               test_event_threaded_timer, NULL);
    2049           1 :         torture_assert(test, te != NULL, "Could not add timer");
    2050             : 
    2051           1 :         ret = pthread_create(&poll_thread, NULL, test_event_poll_thread, ev);
    2052           1 :         torture_assert(test, ret == 0, "Could not create poll thread");
    2053             : 
    2054           1 :         ret = pipe(fds);
    2055           1 :         torture_assert(test, ret == 0, "Could not create pipe");
    2056             : 
    2057           1 :         poll(NULL, 0, 100);
    2058             : 
    2059           1 :         test_event_threaded_lock();
    2060             : 
    2061           1 :         fde = tevent_add_fd(ev, ev, fds[0], TEVENT_FD_READ,
    2062             :                             test_event_threaded_read_handler, &fds[0]);
    2063           1 :         torture_assert(test, fde != NULL, "Could not add fd event");
    2064             : 
    2065           1 :         test_event_threaded_unlock();
    2066             : 
    2067           1 :         poll(NULL, 0, 100);
    2068             : 
    2069           1 :         do_write(fds[1], &c, 1);
    2070             : 
    2071           1 :         poll(NULL, 0, 100);
    2072             : 
    2073           1 :         test_event_threaded_lock();
    2074           1 :         do_shutdown = true;
    2075           1 :         test_event_threaded_unlock();
    2076             : 
    2077           1 :         do_write(fds[1], &c, 1);
    2078             : 
    2079           1 :         ret = pthread_join(poll_thread, NULL);
    2080           1 :         torture_assert(test, ret == 0, "pthread_join failed");
    2081             : 
    2082           0 :         return true;
    2083             : }
    2084             : 
    2085             : #define NUM_TEVENT_THREADS 100
    2086             : 
    2087             : /* Ugly, but needed for torture_comment... */
    2088             : static struct torture_context *thread_test_ctx;
    2089             : static pthread_t thread_map[NUM_TEVENT_THREADS];
    2090             : static unsigned thread_counter;
    2091             : 
    2092             : /* Called in master thread context */
    2093         100 : static void callback_nowait(struct tevent_context *ev,
    2094             :                                 struct tevent_immediate *im,
    2095             :                                 void *private_ptr)
    2096             : {
    2097         100 :         pthread_t *thread_id_ptr =
    2098         100 :                 talloc_get_type_abort(private_ptr, pthread_t);
    2099         100 :         unsigned i;
    2100             : 
    2101        5150 :         for (i = 0; i < NUM_TEVENT_THREADS; i++) {
    2102        5050 :                 if (pthread_equal(*thread_id_ptr,
    2103             :                                 thread_map[i])) {
    2104           0 :                         break;
    2105             :                 }
    2106             :         }
    2107         100 :         torture_comment(thread_test_ctx,
    2108             :                         "Callback %u from thread %u\n",
    2109             :                         thread_counter,
    2110             :                         i);
    2111         100 :         thread_counter++;
    2112         100 : }
    2113             : 
    2114             : /* Blast the master tevent_context with a callback, no waiting. */
    2115         100 : static void *thread_fn_nowait(void *private_ptr)
    2116             : {
    2117         100 :         struct tevent_thread_proxy *master_tp =
    2118         100 :                 talloc_get_type_abort(private_ptr, struct tevent_thread_proxy);
    2119         100 :         struct tevent_immediate *im;
    2120         100 :         pthread_t *thread_id_ptr;
    2121             : 
    2122         100 :         im = tevent_create_immediate(NULL);
    2123         100 :         if (im == NULL) {
    2124           0 :                 return NULL;
    2125             :         }
    2126         100 :         thread_id_ptr = talloc(NULL, pthread_t);
    2127         100 :         if (thread_id_ptr == NULL) {
    2128           0 :                 return NULL;
    2129             :         }
    2130         100 :         *thread_id_ptr = pthread_self();
    2131             : 
    2132         100 :         tevent_thread_proxy_schedule(master_tp,
    2133             :                                 &im,
    2134             :                                 callback_nowait,
    2135             :                                 &thread_id_ptr);
    2136         100 :         return NULL;
    2137             : }
    2138             : 
    2139           0 : static void timeout_fn(struct tevent_context *ev,
    2140             :                         struct tevent_timer *te,
    2141             :                         struct timeval tv, void *p)
    2142             : {
    2143           0 :         thread_counter = NUM_TEVENT_THREADS * 10;
    2144           0 : }
    2145             : 
    2146           1 : static bool test_multi_tevent_threaded(struct torture_context *test,
    2147             :                                         const void *test_data)
    2148             : {
    2149           1 :         unsigned i;
    2150           1 :         struct tevent_context *master_ev;
    2151           1 :         struct tevent_thread_proxy *tp;
    2152             : 
    2153           1 :         talloc_disable_null_tracking();
    2154             : 
    2155             :         /* Ugly global stuff. */
    2156           1 :         thread_test_ctx = test;
    2157           1 :         thread_counter = 0;
    2158             : 
    2159           1 :         master_ev = test_tevent_context_init(NULL);
    2160           1 :         if (master_ev == NULL) {
    2161           0 :                 return false;
    2162             :         }
    2163             : 
    2164           1 :         tp = tevent_thread_proxy_create(master_ev);
    2165           1 :         if (tp == NULL) {
    2166           0 :                 torture_fail(test,
    2167             :                         talloc_asprintf(test,
    2168             :                                 "tevent_thread_proxy_create failed\n"));
    2169             :                 talloc_free(master_ev);
    2170             :                 return false;
    2171             :         }
    2172             : 
    2173         101 :         for (i = 0; i < NUM_TEVENT_THREADS; i++) {
    2174         100 :                 int ret = pthread_create(&thread_map[i],
    2175             :                                 NULL,
    2176             :                                 thread_fn_nowait,
    2177             :                                 tp);
    2178         100 :                 if (ret != 0) {
    2179           0 :                         torture_fail(test,
    2180             :                                 talloc_asprintf(test,
    2181             :                                         "Failed to create thread %i, %d\n",
    2182             :                                         i, ret));
    2183             :                         return false;
    2184             :                 }
    2185             :         }
    2186             : 
    2187             :         /* Ensure we don't wait more than 10 seconds. */
    2188           1 :         tevent_add_timer(master_ev,
    2189             :                         master_ev,
    2190             :                         timeval_current_ofs(10,0),
    2191             :                         timeout_fn,
    2192             :                         NULL);
    2193             : 
    2194           1 :         while (thread_counter < NUM_TEVENT_THREADS) {
    2195         107 :                 int ret = tevent_loop_once(master_ev);
    2196         108 :                 torture_assert(test, ret == 0, "tevent_loop_once failed");
    2197             :         }
    2198             : 
    2199           1 :         torture_assert(test, thread_counter == NUM_TEVENT_THREADS,
    2200             :                 "thread_counter fail\n");
    2201             : 
    2202           1 :         talloc_free(master_ev);
    2203           1 :         return true;
    2204             : }
    2205             : 
    2206             : struct reply_state {
    2207             :         struct tevent_thread_proxy *reply_tp;
    2208             :         pthread_t thread_id;
    2209             :         int *p_finished;
    2210             : };
    2211             : 
    2212           0 : static void thread_timeout_fn(struct tevent_context *ev,
    2213             :                         struct tevent_timer *te,
    2214             :                         struct timeval tv, void *p)
    2215             : {
    2216           0 :         int *p_finished = (int *)p;
    2217             : 
    2218           0 :         *p_finished = 2;
    2219           0 : }
    2220             : 
    2221             : /* Called in child-thread context */
    2222         100 : static void thread_callback(struct tevent_context *ev,
    2223             :                                 struct tevent_immediate *im,
    2224             :                                 void *private_ptr)
    2225             : {
    2226         100 :         struct reply_state *rsp =
    2227         100 :                 talloc_get_type_abort(private_ptr, struct reply_state);
    2228             : 
    2229         100 :         talloc_steal(ev, rsp);
    2230         100 :         *rsp->p_finished = 1;
    2231         100 : }
    2232             : 
    2233             : /* Called in master thread context */
    2234         100 : static void master_callback(struct tevent_context *ev,
    2235             :                                 struct tevent_immediate *im,
    2236             :                                 void *private_ptr)
    2237             : {
    2238         200 :         struct reply_state *rsp =
    2239         100 :                 talloc_get_type_abort(private_ptr, struct reply_state);
    2240         100 :         unsigned i;
    2241             : 
    2242         100 :         talloc_steal(ev, rsp);
    2243             : 
    2244        5150 :         for (i = 0; i < NUM_TEVENT_THREADS; i++) {
    2245        5050 :                 if (pthread_equal(rsp->thread_id,
    2246             :                                 thread_map[i])) {
    2247           0 :                         break;
    2248             :                 }
    2249             :         }
    2250         100 :         torture_comment(thread_test_ctx,
    2251             :                         "Callback %u from thread %u\n",
    2252             :                         thread_counter,
    2253             :                         i);
    2254             :         /* Now reply to the thread ! */
    2255         100 :         tevent_thread_proxy_schedule(rsp->reply_tp,
    2256             :                                 &im,
    2257             :                                 thread_callback,
    2258             :                                 &rsp);
    2259             : 
    2260         100 :         thread_counter++;
    2261         100 : }
    2262             : 
    2263         100 : static void *thread_fn_1(void *private_ptr)
    2264             : {
    2265         100 :         struct tevent_thread_proxy *master_tp =
    2266         100 :                 talloc_get_type_abort(private_ptr, struct tevent_thread_proxy);
    2267         100 :         struct tevent_thread_proxy *tp;
    2268         100 :         struct tevent_immediate *im;
    2269         100 :         struct tevent_context *ev;
    2270         100 :         struct reply_state *rsp;
    2271         100 :         int finished = 0;
    2272         100 :         int ret;
    2273             : 
    2274         100 :         ev = tevent_context_init(NULL);
    2275         100 :         if (ev == NULL) {
    2276           0 :                 return NULL;
    2277             :         }
    2278             : 
    2279         100 :         tp = tevent_thread_proxy_create(ev);
    2280          99 :         if (tp == NULL) {
    2281           0 :                 talloc_free(ev);
    2282           0 :                 return NULL;
    2283             :         }
    2284             : 
    2285          99 :         im = tevent_create_immediate(ev);
    2286         100 :         if (im == NULL) {
    2287           0 :                 talloc_free(ev);
    2288           0 :                 return NULL;
    2289             :         }
    2290             : 
    2291         100 :         rsp = talloc(ev, struct reply_state);
    2292          99 :         if (rsp == NULL) {
    2293           0 :                 talloc_free(ev);
    2294           0 :                 return NULL;
    2295             :         }
    2296             : 
    2297          99 :         rsp->thread_id = pthread_self();
    2298          99 :         rsp->reply_tp = tp;
    2299          99 :         rsp->p_finished = &finished;
    2300             : 
    2301             :         /* Introduce a little randomness into the mix.. */
    2302          99 :         usleep(random() % 7000);
    2303             : 
    2304         100 :         tevent_thread_proxy_schedule(master_tp,
    2305             :                                 &im,
    2306             :                                 master_callback,
    2307             :                                 &rsp);
    2308             : 
    2309             :         /* Ensure we don't wait more than 10 seconds. */
    2310         100 :         tevent_add_timer(ev,
    2311             :                         ev,
    2312             :                         timeval_current_ofs(10,0),
    2313             :                         thread_timeout_fn,
    2314             :                         &finished);
    2315             : 
    2316         300 :         while (finished == 0) {
    2317         200 :                 ret = tevent_loop_once(ev);
    2318         200 :                 assert(ret == 0);
    2319             :         }
    2320             : 
    2321         100 :         if (finished > 1) {
    2322             :                 /* Timeout ! */
    2323           0 :                 abort();
    2324             :         }
    2325             : 
    2326             :         /*
    2327             :          * NB. We should talloc_free(ev) here, but if we do
    2328             :          * we currently get hit by helgrind Fix #323432
    2329             :          * "When calling pthread_cond_destroy or pthread_mutex_destroy
    2330             :          * with initializers as argument Helgrind (incorrectly) reports errors."
    2331             :          *
    2332             :          * http://valgrind.10908.n7.nabble.com/Helgrind-3-9-0-false-positive-
    2333             :          * with-pthread-mutex-destroy-td47757.html
    2334             :          *
    2335             :          * Helgrind doesn't understand that the request/reply
    2336             :          * messages provide synchronization between the lock/unlock
    2337             :          * in tevent_thread_proxy_schedule(), and the pthread_destroy()
    2338             :          * when the struct tevent_thread_proxy object is talloc_free'd.
    2339             :          *
    2340             :          * As a work-around for now return ev for the parent thread to free.
    2341             :          */
    2342           0 :         return ev;
    2343             : }
    2344             : 
    2345           1 : static bool test_multi_tevent_threaded_1(struct torture_context *test,
    2346             :                                         const void *test_data)
    2347             : {
    2348           1 :         unsigned i;
    2349           1 :         struct tevent_context *master_ev;
    2350           1 :         struct tevent_thread_proxy *master_tp;
    2351           1 :         int ret;
    2352             : 
    2353           1 :         talloc_disable_null_tracking();
    2354             : 
    2355             :         /* Ugly global stuff. */
    2356           1 :         thread_test_ctx = test;
    2357           1 :         thread_counter = 0;
    2358             : 
    2359           1 :         master_ev = test_tevent_context_init(NULL);
    2360           1 :         if (master_ev == NULL) {
    2361           0 :                 return false;
    2362             :         }
    2363             : 
    2364           1 :         master_tp = tevent_thread_proxy_create(master_ev);
    2365           1 :         if (master_tp == NULL) {
    2366           0 :                 torture_fail(test,
    2367             :                         talloc_asprintf(test,
    2368             :                                 "tevent_thread_proxy_create failed\n"));
    2369             :                 talloc_free(master_ev);
    2370             :                 return false;
    2371             :         }
    2372             : 
    2373         101 :         for (i = 0; i < NUM_TEVENT_THREADS; i++) {
    2374         100 :                 ret = pthread_create(&thread_map[i],
    2375             :                                 NULL,
    2376             :                                 thread_fn_1,
    2377             :                                 master_tp);
    2378         100 :                 if (ret != 0) {
    2379           0 :                         torture_fail(test,
    2380             :                                 talloc_asprintf(test,
    2381             :                                         "Failed to create thread %i, %d\n",
    2382             :                                         i, ret));
    2383             :                                 return false;
    2384             :                 }
    2385             :         }
    2386             : 
    2387         268 :         while (thread_counter < NUM_TEVENT_THREADS) {
    2388         267 :                 ret = tevent_loop_once(master_ev);
    2389         268 :                 torture_assert(test, ret == 0, "tevent_loop_once failed");
    2390             :         }
    2391             : 
    2392             :         /* Wait for all the threads to finish - join 'em. */
    2393         101 :         for (i = 0; i < NUM_TEVENT_THREADS; i++) {
    2394         100 :                 void *retval;
    2395         100 :                 ret = pthread_join(thread_map[i], &retval);
    2396         100 :                 torture_assert(test, ret == 0, "pthread_join failed");
    2397             :                 /* Free the child thread event context. */
    2398         100 :                 talloc_free(retval);
    2399             :         }
    2400             : 
    2401           1 :         talloc_free(master_ev);
    2402           1 :         return true;
    2403             : }
    2404             : 
    2405             : struct threaded_test_2 {
    2406             :         struct tevent_threaded_context *tctx;
    2407             :         struct tevent_immediate *im;
    2408             :         pthread_t thread_id;
    2409             : };
    2410             : 
    2411             : static void master_callback_2(struct tevent_context *ev,
    2412             :                               struct tevent_immediate *im,
    2413             :                               void *private_data);
    2414             : 
    2415         100 : static void *thread_fn_2(void *private_data)
    2416             : {
    2417         100 :         struct threaded_test_2 *state = private_data;
    2418             : 
    2419         100 :         state->thread_id = pthread_self();
    2420             : 
    2421         100 :         usleep(random() % 7000);
    2422             : 
    2423         100 :         tevent_threaded_schedule_immediate(
    2424         100 :                 state->tctx, state->im, master_callback_2, state);
    2425             : 
    2426         100 :         return NULL;
    2427             : }
    2428             : 
    2429         100 : static void master_callback_2(struct tevent_context *ev,
    2430             :                               struct tevent_immediate *im,
    2431             :                               void *private_data)
    2432             : {
    2433         100 :         struct threaded_test_2 *state = private_data;
    2434         100 :         int i;
    2435             : 
    2436        5050 :         for (i = 0; i < NUM_TEVENT_THREADS; i++) {
    2437        5050 :                 if (pthread_equal(state->thread_id, thread_map[i])) {
    2438           0 :                         break;
    2439             :                 }
    2440             :         }
    2441         100 :         torture_comment(thread_test_ctx,
    2442             :                         "Callback_2 %u from thread %u\n",
    2443             :                         thread_counter,
    2444             :                         i);
    2445         100 :         thread_counter++;
    2446         100 : }
    2447             : 
    2448           1 : static bool test_multi_tevent_threaded_2(struct torture_context *test,
    2449             :                                          const void *test_data)
    2450             : {
    2451           1 :         unsigned i;
    2452             : 
    2453           1 :         struct tevent_context *ev;
    2454           1 :         struct tevent_threaded_context *tctx;
    2455           1 :         int ret;
    2456             : 
    2457           1 :         thread_test_ctx = test;
    2458           1 :         thread_counter = 0;
    2459             : 
    2460           1 :         ev = test_tevent_context_init(test);
    2461           1 :         torture_assert(test, ev != NULL, "tevent_context_init failed");
    2462             : 
    2463             :         /*
    2464             :          * tevent_re_initialise used to have a bug where it did not
    2465             :          * re-initialise the thread support after taking it
    2466             :          * down. Exercise that code path.
    2467             :          */
    2468           1 :         ret = tevent_re_initialise(ev);
    2469           1 :         torture_assert(test, ret == 0, "tevent_re_initialise failed");
    2470             : 
    2471           1 :         tctx = tevent_threaded_context_create(ev, ev);
    2472           1 :         torture_assert(test, tctx != NULL,
    2473             :                        "tevent_threaded_context_create failed");
    2474             : 
    2475         101 :         for (i=0; i<NUM_TEVENT_THREADS; i++) {
    2476         100 :                 struct threaded_test_2 *state;
    2477             : 
    2478         100 :                 state = talloc(ev, struct threaded_test_2);
    2479         100 :                 torture_assert(test, state != NULL, "talloc failed");
    2480             : 
    2481         100 :                 state->tctx = tctx;
    2482         100 :                 state->im = tevent_create_immediate(state);
    2483         100 :                 torture_assert(test, state->im != NULL,
    2484             :                                "tevent_create_immediate failed");
    2485             : 
    2486         100 :                 ret = pthread_create(&thread_map[i], NULL, thread_fn_2, state);
    2487         100 :                 torture_assert(test, ret == 0, "pthread_create failed");
    2488             :         }
    2489             : 
    2490         162 :         while (thread_counter < NUM_TEVENT_THREADS) {
    2491         161 :                 ret = tevent_loop_once(ev);
    2492         162 :                 torture_assert(test, ret == 0, "tevent_loop_once failed");
    2493             :         }
    2494             : 
    2495             :         /* Wait for all the threads to finish - join 'em. */
    2496         101 :         for (i = 0; i < NUM_TEVENT_THREADS; i++) {
    2497         100 :                 void *retval;
    2498         100 :                 ret = pthread_join(thread_map[i], &retval);
    2499         100 :                 torture_assert(test, ret == 0, "pthread_join failed");
    2500             :                 /* Free the child thread event context. */
    2501             :         }
    2502             : 
    2503           1 :         talloc_free(tctx);
    2504           1 :         talloc_free(ev);
    2505           1 :         return true;
    2506             : }
    2507             : 
    2508             : struct test_cached_pid_thread_state {
    2509             :         pid_t thread_cached_pid;
    2510             :         pid_t thread_pid;
    2511             : };
    2512             : 
    2513           1 : static void *test_cached_pid_thread(void *private_data)
    2514             : {
    2515           1 :         struct test_cached_pid_thread_state *state =
    2516             :                 (struct test_cached_pid_thread_state *)private_data;
    2517             : 
    2518           1 :         state->thread_cached_pid = tevent_cached_getpid();
    2519           1 :         state->thread_pid = getpid();
    2520             : 
    2521           1 :         return NULL;
    2522             : }
    2523             : #endif
    2524             : 
    2525           1 : static bool test_cached_pid(struct torture_context *test,
    2526             :                             const void *test_data)
    2527             : {
    2528           1 :         pid_t parent_pid = getpid();
    2529           1 :         pid_t child_pid;
    2530           1 :         pid_t finished_pid;
    2531           1 :         int child_status;
    2532             : 
    2533           1 :         torture_assert(test, tevent_cached_getpid() == parent_pid, "tevent_cached_getpid()");
    2534             : 
    2535             : #ifdef HAVE_PTHREAD
    2536             :         {
    2537           1 :                 struct test_cached_pid_thread_state state = { .thread_cached_pid = -1, };
    2538           1 :                 pthread_t thread;
    2539           1 :                 void *retval = NULL;
    2540           1 :                 int ret;
    2541             : 
    2542           1 :                 ret = pthread_create(&thread, NULL, test_cached_pid_thread, &state);
    2543           1 :                 torture_assert(test, ret == 0, "pthread_create failed");
    2544             : 
    2545           1 :                 ret = pthread_join(thread, &retval);
    2546           1 :                 torture_assert(test, ret == 0, "pthread_join failed");
    2547             : 
    2548           1 :                 torture_assert(test, state.thread_pid == parent_pid, "getpid() in thread");
    2549           1 :                 torture_assert(test, state.thread_cached_pid == parent_pid, "tevent_cached_getpid() in thread");
    2550             :         }
    2551             : #endif /* HAVE_PTHREAD */
    2552             : 
    2553           1 :         child_pid = fork();
    2554           2 :         if (child_pid == 0) {
    2555             :                 /* child */
    2556           1 :                 pid_t pid = getpid();
    2557           1 :                 pid_t cached_pid = tevent_cached_getpid();
    2558             : 
    2559           1 :                 if (parent_pid == pid) {
    2560           0 :                         exit(1);
    2561             :                 }
    2562           1 :                 if (pid != cached_pid) {
    2563           0 :                         exit(2);
    2564             :                 }
    2565           1 :                 exit(0);
    2566             :         }
    2567           1 :         torture_assert(test, child_pid > 0, "fork failed");
    2568             : 
    2569           1 :         finished_pid = waitpid(child_pid, &child_status, 0);
    2570           1 :         torture_assert(test, finished_pid == child_pid, "wrong child");
    2571           1 :         torture_assert(test, child_status == 0, "child_status");
    2572             : 
    2573           0 :         return true;
    2574             : }
    2575             : 
    2576        2358 : struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx)
    2577             : {
    2578        2358 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "event");
    2579        2358 :         const char **list = tevent_backend_list(suite);
    2580         125 :         int i;
    2581             : 
    2582       11915 :         for (i=0;list && list[i];i++) {
    2583         500 :                 struct torture_suite *backend_suite;
    2584             : 
    2585        9432 :                 backend_suite = torture_suite_create(mem_ctx, list[i]);
    2586             : 
    2587        9432 :                 torture_suite_add_simple_tcase_const(backend_suite,
    2588             :                                                "context",
    2589             :                                                test_event_context,
    2590        8932 :                                                (const void *)list[i]);
    2591        9432 :                 torture_suite_add_simple_tcase_const(backend_suite,
    2592             :                                                "fd_speed1",
    2593             :                                                test_fd_speed1,
    2594        8932 :                                                (const void *)list[i]);
    2595        9432 :                 torture_suite_add_simple_tcase_const(backend_suite,
    2596             :                                                "fd_speed2",
    2597             :                                                test_fd_speed2,
    2598        8932 :                                                (const void *)list[i]);
    2599        9432 :                 torture_suite_add_simple_tcase_const(backend_suite,
    2600             :                                                "fd_speed3",
    2601             :                                                test_fd_speed3,
    2602        8932 :                                                (const void *)list[i]);
    2603        9432 :                 torture_suite_add_simple_tcase_const(backend_suite,
    2604             :                                                "fd1",
    2605             :                                                test_event_fd1,
    2606        8932 :                                                (const void *)list[i]);
    2607        9432 :                 torture_suite_add_simple_tcase_const(backend_suite,
    2608             :                                                "fd2",
    2609             :                                                test_event_fd2,
    2610        8932 :                                                (const void *)list[i]);
    2611        9432 :                 torture_suite_add_simple_tcase_const(backend_suite,
    2612             :                                                "fd3",
    2613             :                                                test_event_fd3,
    2614        8932 :                                                (const void *)list[i]);
    2615        9432 :                 torture_suite_add_simple_tcase_const(backend_suite,
    2616             :                                                "wrapper",
    2617             :                                                test_wrapper,
    2618        8932 :                                                (const void *)list[i]);
    2619        9432 :                 torture_suite_add_simple_tcase_const(backend_suite,
    2620             :                                                "free_wrapper",
    2621             :                                                test_free_wrapper,
    2622        8932 :                                                (const void *)list[i]);
    2623             : 
    2624        9432 :                 torture_suite_add_suite(suite, backend_suite);
    2625             :         }
    2626             : 
    2627             : #ifdef HAVE_PTHREAD
    2628        2358 :         torture_suite_add_simple_tcase_const(suite, "threaded_poll_mt",
    2629             :                                              test_event_context_threaded,
    2630             :                                              NULL);
    2631             : 
    2632        2358 :         torture_suite_add_simple_tcase_const(suite, "multi_tevent_threaded",
    2633             :                                              test_multi_tevent_threaded,
    2634             :                                              NULL);
    2635             : 
    2636        2358 :         torture_suite_add_simple_tcase_const(suite, "multi_tevent_threaded_1",
    2637             :                                              test_multi_tevent_threaded_1,
    2638             :                                              NULL);
    2639             : 
    2640        2358 :         torture_suite_add_simple_tcase_const(suite, "multi_tevent_threaded_2",
    2641             :                                              test_multi_tevent_threaded_2,
    2642             :                                              NULL);
    2643             : 
    2644             : #endif
    2645             : 
    2646        2358 :         torture_suite_add_simple_tcase_const(suite, "tevent_cached_getpid",
    2647             :                                              test_cached_pid,
    2648             :                                              NULL);
    2649             : 
    2650        2358 :         return suite;
    2651             : }

Generated by: LCOV version 1.14