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 13316999 : static void do_read(int fd, void *buf, size_t count)
70 : {
71 13316999 : ssize_t ret;
72 :
73 13316999 : do {
74 13316999 : ret = read(fd, buf, count);
75 13316999 : } while (ret == -1 && errno == EINTR);
76 13316999 : }
77 :
78 1316999 : static void fde_handler_read(struct tevent_context *ev_ctx, struct tevent_fd *f,
79 : uint16_t flags, void *private_data)
80 : {
81 1316999 : int *fd = (int *)private_data;
82 1316999 : char c;
83 : #ifdef SA_SIGINFO
84 1316999 : kill(getpid(), SIGUSR1);
85 : #endif
86 1316999 : kill(getpid(), SIGALRM);
87 :
88 1316999 : do_read(fd[0], &c, 1);
89 1316999 : fde_count++;
90 1316999 : }
91 :
92 13317045 : static void do_write(int fd, void *buf, size_t count)
93 : {
94 13317045 : ssize_t ret;
95 :
96 13317045 : do {
97 13317045 : ret = write(fd, buf, count);
98 13317045 : } while (ret == -1 && errno == EINTR);
99 13317045 : }
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 1317001 : static void fde_handler_write(struct tevent_context *ev_ctx, struct tevent_fd *f,
118 : uint16_t flags, void *private_data)
119 : {
120 1317001 : int *fd = (int *)private_data;
121 1317001 : char c = 0;
122 :
123 1317001 : do_write(fd[1], &c, 1);
124 1317001 : }
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 2634002 : 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 2634002 : int *countp = (int *)private_data;
162 2634002 : (*countp) += count;
163 2634002 : }
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 5268001 : while (!finished) {
236 5267997 : errno = 0;
237 5267997 : 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 121 : int ret = tevent_loop_once(master_ev);
2196 122 : 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 100 : if (tp == NULL) {
2281 0 : talloc_free(ev);
2282 0 : return NULL;
2283 : }
2284 :
2285 100 : im = tevent_create_immediate(ev);
2286 99 : if (im == NULL) {
2287 0 : talloc_free(ev);
2288 0 : return NULL;
2289 : }
2290 :
2291 99 : rsp = talloc(ev, struct reply_state);
2292 98 : if (rsp == NULL) {
2293 0 : talloc_free(ev);
2294 0 : return NULL;
2295 : }
2296 :
2297 98 : rsp->thread_id = pthread_self();
2298 98 : rsp->reply_tp = tp;
2299 98 : rsp->p_finished = &finished;
2300 :
2301 : /* Introduce a little randomness into the mix.. */
2302 98 : 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 264 : while (thread_counter < NUM_TEVENT_THREADS) {
2388 263 : ret = tevent_loop_once(master_ev);
2389 264 : 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 99 : 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 166 : while (thread_counter < NUM_TEVENT_THREADS) {
2491 165 : ret = tevent_loop_once(ev);
2492 166 : 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 2354 : struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx)
2577 : {
2578 2354 : struct torture_suite *suite = torture_suite_create(mem_ctx, "event");
2579 2354 : const char **list = tevent_backend_list(suite);
2580 125 : int i;
2581 :
2582 11895 : for (i=0;list && list[i];i++) {
2583 500 : struct torture_suite *backend_suite;
2584 :
2585 9416 : backend_suite = torture_suite_create(mem_ctx, list[i]);
2586 :
2587 9416 : torture_suite_add_simple_tcase_const(backend_suite,
2588 : "context",
2589 : test_event_context,
2590 8916 : (const void *)list[i]);
2591 9416 : torture_suite_add_simple_tcase_const(backend_suite,
2592 : "fd_speed1",
2593 : test_fd_speed1,
2594 8916 : (const void *)list[i]);
2595 9416 : torture_suite_add_simple_tcase_const(backend_suite,
2596 : "fd_speed2",
2597 : test_fd_speed2,
2598 8916 : (const void *)list[i]);
2599 9416 : torture_suite_add_simple_tcase_const(backend_suite,
2600 : "fd_speed3",
2601 : test_fd_speed3,
2602 8916 : (const void *)list[i]);
2603 9416 : torture_suite_add_simple_tcase_const(backend_suite,
2604 : "fd1",
2605 : test_event_fd1,
2606 8916 : (const void *)list[i]);
2607 9416 : torture_suite_add_simple_tcase_const(backend_suite,
2608 : "fd2",
2609 : test_event_fd2,
2610 8916 : (const void *)list[i]);
2611 9416 : torture_suite_add_simple_tcase_const(backend_suite,
2612 : "fd3",
2613 : test_event_fd3,
2614 8916 : (const void *)list[i]);
2615 9416 : torture_suite_add_simple_tcase_const(backend_suite,
2616 : "wrapper",
2617 : test_wrapper,
2618 8916 : (const void *)list[i]);
2619 9416 : torture_suite_add_simple_tcase_const(backend_suite,
2620 : "free_wrapper",
2621 : test_free_wrapper,
2622 8916 : (const void *)list[i]);
2623 :
2624 9416 : torture_suite_add_suite(suite, backend_suite);
2625 : }
2626 :
2627 : #ifdef HAVE_PTHREAD
2628 2354 : torture_suite_add_simple_tcase_const(suite, "threaded_poll_mt",
2629 : test_event_context_threaded,
2630 : NULL);
2631 :
2632 2354 : torture_suite_add_simple_tcase_const(suite, "multi_tevent_threaded",
2633 : test_multi_tevent_threaded,
2634 : NULL);
2635 :
2636 2354 : torture_suite_add_simple_tcase_const(suite, "multi_tevent_threaded_1",
2637 : test_multi_tevent_threaded_1,
2638 : NULL);
2639 :
2640 2354 : torture_suite_add_simple_tcase_const(suite, "multi_tevent_threaded_2",
2641 : test_multi_tevent_threaded_2,
2642 : NULL);
2643 :
2644 : #endif
2645 :
2646 2354 : torture_suite_add_simple_tcase_const(suite, "tevent_cached_getpid",
2647 : test_cached_pid,
2648 : NULL);
2649 :
2650 2354 : return suite;
2651 : }
|