2 Unix SMB/CIFS implementation.
4 testing of the events subsystem
6 Copyright (C) Stefan Metzmacher 2006-2009
7 Copyright (C) Jeremy Allison 2013
9 ** NOTE! The following LGPL license applies to the tevent
10 ** library. This does NOT imply that all of Samba is released
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.
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.
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/>.
28 #define TEVENT_DEPRECATED 1
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"
36 #include "system/threads.h"
42 static void do_read(int fd
, void *buf
, size_t count
)
47 ret
= read(fd
, buf
, count
);
48 } while (ret
== -1 && errno
== EINTR
);
51 static void fde_handler_read(struct tevent_context
*ev_ctx
, struct tevent_fd
*f
,
52 uint16_t flags
, void *private_data
)
54 int *fd
= (int *)private_data
;
57 kill(getpid(), SIGUSR1
);
59 kill(getpid(), SIGALRM
);
61 do_read(fd
[0], &c
, 1);
65 static void do_write(int fd
, void *buf
, size_t count
)
70 ret
= write(fd
, buf
, count
);
71 } while (ret
== -1 && errno
== EINTR
);
74 static void fde_handler_write(struct tevent_context
*ev_ctx
, struct tevent_fd
*f
,
75 uint16_t flags
, void *private_data
)
77 int *fd
= (int *)private_data
;
80 do_write(fd
[1], &c
, 1);
84 /* This will only fire if the fd's returned from pipe() are bi-directional. */
85 static void fde_handler_read_1(struct tevent_context
*ev_ctx
, struct tevent_fd
*f
,
86 uint16_t flags
, void *private_data
)
88 int *fd
= (int *)private_data
;
91 kill(getpid(), SIGUSR1
);
93 kill(getpid(), SIGALRM
);
95 do_read(fd
[1], &c
, 1);
99 /* This will only fire if the fd's returned from pipe() are bi-directional. */
100 static void fde_handler_write_1(struct tevent_context
*ev_ctx
, struct tevent_fd
*f
,
101 uint16_t flags
, void *private_data
)
103 int *fd
= (int *)private_data
;
105 do_write(fd
[0], &c
, 1);
108 static void finished_handler(struct tevent_context
*ev_ctx
, struct tevent_timer
*te
,
109 struct timeval tval
, void *private_data
)
111 int *finished
= (int *)private_data
;
115 static void count_handler(struct tevent_context
*ev_ctx
, struct tevent_signal
*te
,
116 int signum
, int count
, void *info
, void *private_data
)
118 int *countp
= (int *)private_data
;
122 static bool test_event_context(struct torture_context
*test
,
123 const void *test_data
)
125 struct tevent_context
*ev_ctx
;
126 int fd
[2] = { -1, -1 };
127 const char *backend
= (const char *)test_data
;
128 int alarm_count
=0, info_count
=0;
129 struct tevent_fd
*fde_read
;
130 struct tevent_fd
*fde_read_1
;
131 struct tevent_fd
*fde_write
;
132 struct tevent_fd
*fde_write_1
;
134 struct tevent_signal
*se1
= NULL
;
137 struct tevent_signal
*se2
= NULL
;
140 struct tevent_signal
*se3
= NULL
;
146 ev_ctx
= tevent_context_init_byname(test
, backend
);
147 if (ev_ctx
== NULL
) {
148 torture_comment(test
, "event backend '%s' not supported\n", backend
);
152 torture_comment(test
, "backend '%s' - %s\n",
153 backend
, __FUNCTION__
);
160 torture_assert_int_equal(test
, ret
, 0, "pipe failed");
162 fde_read
= tevent_add_fd(ev_ctx
, ev_ctx
, fd
[0], TEVENT_FD_READ
,
163 fde_handler_read
, fd
);
164 fde_write_1
= tevent_add_fd(ev_ctx
, ev_ctx
, fd
[0], TEVENT_FD_WRITE
,
165 fde_handler_write_1
, fd
);
167 fde_write
= tevent_add_fd(ev_ctx
, ev_ctx
, fd
[1], TEVENT_FD_WRITE
,
168 fde_handler_write
, fd
);
169 fde_read_1
= tevent_add_fd(ev_ctx
, ev_ctx
, fd
[1], TEVENT_FD_READ
,
170 fde_handler_read_1
, fd
);
172 tevent_fd_set_auto_close(fde_read
);
173 tevent_fd_set_auto_close(fde_write
);
175 tevent_add_timer(ev_ctx
, ev_ctx
, timeval_current_ofs(2,0),
176 finished_handler
, &finished
);
179 se1
= tevent_add_signal(ev_ctx
, ev_ctx
, SIGALRM
, SA_RESTART
, count_handler
, &alarm_count
);
180 torture_assert(test
, se1
!= NULL
, "failed to setup se1");
183 se2
= tevent_add_signal(ev_ctx
, ev_ctx
, SIGALRM
, SA_RESETHAND
, count_handler
, &alarm_count
);
184 torture_assert(test
, se2
!= NULL
, "failed to setup se2");
187 se3
= tevent_add_signal(ev_ctx
, ev_ctx
, SIGUSR1
, SA_SIGINFO
, count_handler
, &info_count
);
188 torture_assert(test
, se3
!= NULL
, "failed to setup se3");
191 t
= timeval_current();
194 if (tevent_loop_once(ev_ctx
) == -1) {
196 torture_fail(test
, talloc_asprintf(test
, "Failed event loop %s\n", strerror(errno
)));
201 talloc_free(fde_read_1
);
202 talloc_free(fde_write_1
);
203 talloc_free(fde_read
);
204 talloc_free(fde_write
);
206 while (alarm_count
< fde_count
+1) {
207 if (tevent_loop_once(ev_ctx
) == -1) {
212 torture_comment(test
, "Got %.2f pipe events/sec\n", fde_count
/timeval_elapsed(&t
));
218 torture_assert_int_equal(test
, alarm_count
, 1+fde_count
, "alarm count mismatch");
222 * we do not call talloc_free(se2)
223 * because it is already gone,
224 * after triggering the event handler.
230 torture_assert_int_equal(test
, info_count
, fde_count
, "info count mismatch");
238 struct test_event_fd1_state
{
239 struct torture_context
*tctx
;
241 struct tevent_context
*ev
;
243 struct tevent_timer
*te
;
244 struct tevent_fd
*fde0
;
245 struct tevent_fd
*fde1
;
255 static void test_event_fd1_fde_handler(struct tevent_context
*ev_ctx
,
256 struct tevent_fd
*fde
,
260 struct test_event_fd1_state
*state
=
261 (struct test_event_fd1_state
*)private_data
;
263 if (state
->drain_done
) {
264 state
->finished
= true;
265 state
->error
= __location__
;
273 if (!(flags
& TEVENT_FD_READ
)) {
274 state
->finished
= true;
275 state
->error
= __location__
;
279 ret
= read(state
->sock
[0], &c
, 1);
287 tevent_fd_set_flags(fde
, 0);
288 state
->drain_done
= true;
292 if (!state
->got_write
) {
295 if (flags
!= TEVENT_FD_WRITE
) {
296 state
->finished
= true;
297 state
->error
= __location__
;
300 state
->got_write
= true;
303 * we write to the other socket...
305 do_write(state
->sock
[1], &c
, 1);
306 TEVENT_FD_NOT_WRITEABLE(fde
);
307 TEVENT_FD_READABLE(fde
);
311 if (!state
->got_read
) {
312 if (flags
!= TEVENT_FD_READ
) {
313 state
->finished
= true;
314 state
->error
= __location__
;
317 state
->got_read
= true;
319 TEVENT_FD_NOT_READABLE(fde
);
323 state
->finished
= true;
324 state
->error
= __location__
;
328 static void test_event_fd1_finished(struct tevent_context
*ev_ctx
,
329 struct tevent_timer
*te
,
333 struct test_event_fd1_state
*state
=
334 (struct test_event_fd1_state
*)private_data
;
336 if (state
->drain_done
) {
337 state
->finished
= true;
341 if (!state
->got_write
) {
342 state
->finished
= true;
343 state
->error
= __location__
;
347 if (!state
->got_read
) {
348 state
->finished
= true;
349 state
->error
= __location__
;
354 if (state
->loop_count
> 3) {
355 state
->finished
= true;
356 state
->error
= __location__
;
360 state
->got_write
= false;
361 state
->got_read
= false;
363 tevent_fd_set_flags(state
->fde0
, TEVENT_FD_WRITE
);
365 if (state
->loop_count
> 2) {
367 TALLOC_FREE(state
->fde1
);
368 TEVENT_FD_READABLE(state
->fde0
);
371 state
->te
= tevent_add_timer(state
->ev
, state
->ev
,
372 timeval_current_ofs(0,2000),
373 test_event_fd1_finished
, state
);
376 static bool test_event_fd1(struct torture_context
*tctx
,
377 const void *test_data
)
379 struct test_event_fd1_state state
;
384 state
.backend
= (const char *)test_data
;
386 state
.ev
= tevent_context_init_byname(tctx
, state
.backend
);
387 if (state
.ev
== NULL
) {
388 torture_skip(tctx
, talloc_asprintf(tctx
,
389 "event backend '%s' not supported\n",
394 tevent_set_debug_stderr(state
.ev
);
395 torture_comment(tctx
, "backend '%s' - %s\n",
396 state
.backend
, __FUNCTION__
);
399 * This tests the following:
401 * It monitors the state of state.sock[0]
402 * with tevent_fd, but we never read/write on state.sock[0]
403 * while state.sock[1] * is only used to write a few bytes.
406 * - we wait only for TEVENT_FD_WRITE on state.sock[0]
407 * - we write 1 byte to state.sock[1]
408 * - we wait only for TEVENT_FD_READ on state.sock[0]
409 * - we disable events on state.sock[0]
410 * - the timer event restarts the loop
411 * Then we close state.sock[1]
413 * - we wait for TEVENT_FD_READ/WRITE on state.sock[0]
414 * - we try to read 1 byte
415 * - if the read gets an error of returns 0
416 * we disable the event handler
417 * - the timer finishes the test
422 ret
= socketpair(AF_UNIX
, SOCK_STREAM
, 0, state
.sock
);
423 torture_assert(tctx
, ret
== 0, "socketpair() failed");
425 state
.te
= tevent_add_timer(state
.ev
, state
.ev
,
426 timeval_current_ofs(0,10000),
427 test_event_fd1_finished
, &state
);
428 state
.fde0
= tevent_add_fd(state
.ev
, state
.ev
,
429 state
.sock
[0], TEVENT_FD_WRITE
,
430 test_event_fd1_fde_handler
, &state
);
431 /* state.fde1 is only used to auto close */
432 state
.fde1
= tevent_add_fd(state
.ev
, state
.ev
,
434 test_event_fd1_fde_handler
, &state
);
436 tevent_fd_set_auto_close(state
.fde0
);
437 tevent_fd_set_auto_close(state
.fde1
);
439 while (!state
.finished
) {
441 if (tevent_loop_once(state
.ev
) == -1) {
442 talloc_free(state
.ev
);
443 torture_fail(tctx
, talloc_asprintf(tctx
,
444 "Failed event loop %s\n",
449 talloc_free(state
.ev
);
451 torture_assert(tctx
, state
.error
== NULL
, talloc_asprintf(tctx
,
457 struct test_event_fd2_state
{
458 struct torture_context
*tctx
;
460 struct tevent_context
*ev
;
461 struct tevent_timer
*te
;
462 struct test_event_fd2_sock
{
463 struct test_event_fd2_state
*state
;
465 struct tevent_fd
*fde
;
474 static void test_event_fd2_sock_handler(struct tevent_context
*ev_ctx
,
475 struct tevent_fd
*fde
,
479 struct test_event_fd2_sock
*cur_sock
=
480 (struct test_event_fd2_sock
*)private_data
;
481 struct test_event_fd2_state
*state
= cur_sock
->state
;
482 struct test_event_fd2_sock
*oth_sock
= NULL
;
486 if (cur_sock
== &state
->sock0
) {
487 oth_sock
= &state
->sock1
;
489 oth_sock
= &state
->sock0
;
492 if (oth_sock
->num_written
== 1) {
493 if (flags
!= (TEVENT_FD_READ
| TEVENT_FD_WRITE
)) {
494 state
->finished
= true;
495 state
->error
= __location__
;
500 if (cur_sock
->num_read
== oth_sock
->num_written
) {
501 state
->finished
= true;
502 state
->error
= __location__
;
506 if (!(flags
& TEVENT_FD_READ
)) {
507 state
->finished
= true;
508 state
->error
= __location__
;
512 if (oth_sock
->num_read
>= PIPE_BUF
) {
514 * On Linux we become writable once we've read
515 * one byte. On Solaris we only become writable
516 * again once we've read 4096 bytes. PIPE_BUF
517 * is probably a safe bet to test against.
519 * There should be room to write a byte again
521 if (!(flags
& TEVENT_FD_WRITE
)) {
522 state
->finished
= true;
523 state
->error
= __location__
;
528 if ((flags
& TEVENT_FD_WRITE
) && !cur_sock
->got_full
) {
529 v
= (uint8_t)cur_sock
->num_written
;
530 ret
= write(cur_sock
->fd
, &v
, 1);
532 state
->finished
= true;
533 state
->error
= __location__
;
536 cur_sock
->num_written
++;
537 if (cur_sock
->num_written
> 0x80000000) {
538 state
->finished
= true;
539 state
->error
= __location__
;
545 if (!cur_sock
->got_full
) {
546 cur_sock
->got_full
= true;
548 if (!oth_sock
->got_full
) {
551 * lets wait for oth_sock
554 tevent_fd_set_flags(cur_sock
->fde
, 0);
559 * oth_sock waited for cur_sock,
562 tevent_fd_set_flags(oth_sock
->fde
,
563 TEVENT_FD_READ
|TEVENT_FD_WRITE
);
566 ret
= read(cur_sock
->fd
, &v
, 1);
568 state
->finished
= true;
569 state
->error
= __location__
;
572 c
= (uint8_t)cur_sock
->num_read
;
574 state
->finished
= true;
575 state
->error
= __location__
;
578 cur_sock
->num_read
++;
580 if (cur_sock
->num_read
< oth_sock
->num_written
) {
581 /* there is more to read */
585 * we read everything, we need to remove TEVENT_FD_WRITE
588 TEVENT_FD_NOT_WRITEABLE(cur_sock
->fde
);
590 if (oth_sock
->num_read
== cur_sock
->num_written
) {
592 * both directions are finished
594 state
->finished
= true;
600 static void test_event_fd2_finished(struct tevent_context
*ev_ctx
,
601 struct tevent_timer
*te
,
605 struct test_event_fd2_state
*state
=
606 (struct test_event_fd2_state
*)private_data
;
609 * this should never be triggered
611 state
->finished
= true;
612 state
->error
= __location__
;
615 static bool test_event_fd2(struct torture_context
*tctx
,
616 const void *test_data
)
618 struct test_event_fd2_state state
;
624 state
.backend
= (const char *)test_data
;
626 state
.ev
= tevent_context_init_byname(tctx
, state
.backend
);
627 if (state
.ev
== NULL
) {
628 torture_skip(tctx
, talloc_asprintf(tctx
,
629 "event backend '%s' not supported\n",
634 tevent_set_debug_stderr(state
.ev
);
635 torture_comment(tctx
, "backend '%s' - %s\n",
636 state
.backend
, __FUNCTION__
);
639 * This tests the following
641 * - We write 1 byte to each socket
642 * - We wait for TEVENT_FD_READ/WRITE on both sockets
643 * - When we get TEVENT_FD_WRITE we write 1 byte
644 * until both socket buffers are full, which
645 * means both sockets only get TEVENT_FD_READ.
646 * - Then we read 1 byte until we have consumed
647 * all bytes the other end has written.
651 socketpair(AF_UNIX
, SOCK_STREAM
, 0, sock
);
654 * the timer should never expire
656 state
.te
= tevent_add_timer(state
.ev
, state
.ev
,
657 timeval_current_ofs(600, 0),
658 test_event_fd2_finished
, &state
);
659 state
.sock0
.state
= &state
;
660 state
.sock0
.fd
= sock
[0];
661 state
.sock0
.fde
= tevent_add_fd(state
.ev
, state
.ev
,
663 TEVENT_FD_READ
| TEVENT_FD_WRITE
,
664 test_event_fd2_sock_handler
,
666 state
.sock1
.state
= &state
;
667 state
.sock1
.fd
= sock
[1];
668 state
.sock1
.fde
= tevent_add_fd(state
.ev
, state
.ev
,
670 TEVENT_FD_READ
| TEVENT_FD_WRITE
,
671 test_event_fd2_sock_handler
,
674 tevent_fd_set_auto_close(state
.sock0
.fde
);
675 tevent_fd_set_auto_close(state
.sock1
.fde
);
677 do_write(state
.sock0
.fd
, &c
, 1);
678 state
.sock0
.num_written
++;
679 do_write(state
.sock1
.fd
, &c
, 1);
680 state
.sock1
.num_written
++;
682 while (!state
.finished
) {
684 if (tevent_loop_once(state
.ev
) == -1) {
685 talloc_free(state
.ev
);
686 torture_fail(tctx
, talloc_asprintf(tctx
,
687 "Failed event loop %s\n",
692 talloc_free(state
.ev
);
694 torture_assert(tctx
, state
.error
== NULL
, talloc_asprintf(tctx
,
700 struct test_wrapper_state
{
701 struct torture_context
*tctx
;
703 int num_wrap_handlers
;
706 static bool test_wrapper_before_use(struct tevent_context
*wrap_ev
,
708 struct tevent_context
*main_ev
,
709 const char *location
)
711 struct test_wrapper_state
*state
=
712 talloc_get_type_abort(private_data
,
713 struct test_wrapper_state
);
715 torture_comment(state
->tctx
, "%s\n", __func__
);
716 state
->num_wrap_handlers
++;
720 static void test_wrapper_after_use(struct tevent_context
*wrap_ev
,
722 struct tevent_context
*main_ev
,
723 const char *location
)
725 struct test_wrapper_state
*state
=
726 talloc_get_type_abort(private_data
,
727 struct test_wrapper_state
);
729 torture_comment(state
->tctx
, "%s\n", __func__
);
730 state
->num_wrap_handlers
++;
733 static void test_wrapper_before_fd_handler(struct tevent_context
*wrap_ev
,
735 struct tevent_context
*main_ev
,
736 struct tevent_fd
*fde
,
738 const char *handler_name
,
739 const char *location
)
741 struct test_wrapper_state
*state
=
742 talloc_get_type_abort(private_data
,
743 struct test_wrapper_state
);
745 torture_comment(state
->tctx
, "%s\n", __func__
);
746 state
->num_wrap_handlers
++;
749 static void test_wrapper_after_fd_handler(struct tevent_context
*wrap_ev
,
751 struct tevent_context
*main_ev
,
752 struct tevent_fd
*fde
,
754 const char *handler_name
,
755 const char *location
)
757 struct test_wrapper_state
*state
=
758 talloc_get_type_abort(private_data
,
759 struct test_wrapper_state
);
761 torture_comment(state
->tctx
, "%s\n", __func__
);
762 state
->num_wrap_handlers
++;
765 static void test_wrapper_before_timer_handler(struct tevent_context
*wrap_ev
,
767 struct tevent_context
*main_ev
,
768 struct tevent_timer
*te
,
769 struct timeval requested_time
,
770 struct timeval trigger_time
,
771 const char *handler_name
,
772 const char *location
)
774 struct test_wrapper_state
*state
=
775 talloc_get_type_abort(private_data
,
776 struct test_wrapper_state
);
778 torture_comment(state
->tctx
, "%s\n", __func__
);
779 state
->num_wrap_handlers
++;
782 static void test_wrapper_after_timer_handler(struct tevent_context
*wrap_ev
,
784 struct tevent_context
*main_ev
,
785 struct tevent_timer
*te
,
786 struct timeval requested_time
,
787 struct timeval trigger_time
,
788 const char *handler_name
,
789 const char *location
)
791 struct test_wrapper_state
*state
=
792 talloc_get_type_abort(private_data
,
793 struct test_wrapper_state
);
795 torture_comment(state
->tctx
, "%s\n", __func__
);
796 state
->num_wrap_handlers
++;
799 static void test_wrapper_before_immediate_handler(struct tevent_context
*wrap_ev
,
801 struct tevent_context
*main_ev
,
802 struct tevent_immediate
*im
,
803 const char *handler_name
,
804 const char *location
)
806 struct test_wrapper_state
*state
=
807 talloc_get_type_abort(private_data
,
808 struct test_wrapper_state
);
810 torture_comment(state
->tctx
, "%s\n", __func__
);
811 state
->num_wrap_handlers
++;
814 static void test_wrapper_after_immediate_handler(struct tevent_context
*wrap_ev
,
816 struct tevent_context
*main_ev
,
817 struct tevent_immediate
*im
,
818 const char *handler_name
,
819 const char *location
)
821 struct test_wrapper_state
*state
=
822 talloc_get_type_abort(private_data
,
823 struct test_wrapper_state
);
825 torture_comment(state
->tctx
, "%s\n", __func__
);
826 state
->num_wrap_handlers
++;
829 static void test_wrapper_before_signal_handler(struct tevent_context
*wrap_ev
,
831 struct tevent_context
*main_ev
,
832 struct tevent_signal
*se
,
836 const char *handler_name
,
837 const char *location
)
839 struct test_wrapper_state
*state
=
840 talloc_get_type_abort(private_data
,
841 struct test_wrapper_state
);
843 torture_comment(state
->tctx
, "%s\n", __func__
);
844 state
->num_wrap_handlers
++;
847 static void test_wrapper_after_signal_handler(struct tevent_context
*wrap_ev
,
849 struct tevent_context
*main_ev
,
850 struct tevent_signal
*se
,
854 const char *handler_name
,
855 const char *location
)
857 struct test_wrapper_state
*state
=
858 talloc_get_type_abort(private_data
,
859 struct test_wrapper_state
);
861 torture_comment(state
->tctx
, "%s\n", __func__
);
862 state
->num_wrap_handlers
++;
865 static const struct tevent_wrapper_ops test_wrapper_ops
= {
866 .name
= "test_wrapper",
867 .before_use
= test_wrapper_before_use
,
868 .after_use
= test_wrapper_after_use
,
869 .before_fd_handler
= test_wrapper_before_fd_handler
,
870 .after_fd_handler
= test_wrapper_after_fd_handler
,
871 .before_timer_handler
= test_wrapper_before_timer_handler
,
872 .after_timer_handler
= test_wrapper_after_timer_handler
,
873 .before_immediate_handler
= test_wrapper_before_immediate_handler
,
874 .after_immediate_handler
= test_wrapper_after_immediate_handler
,
875 .before_signal_handler
= test_wrapper_before_signal_handler
,
876 .after_signal_handler
= test_wrapper_after_signal_handler
,
879 static void test_wrapper_timer_handler(struct tevent_context
*ev
,
880 struct tevent_timer
*te
,
884 struct test_wrapper_state
*state
=
885 (struct test_wrapper_state
*)private_data
;
888 torture_comment(state
->tctx
, "timer handler\n");
895 static void test_wrapper_fd_handler(struct tevent_context
*ev
,
896 struct tevent_fd
*fde
,
897 unsigned short fd_flags
,
900 struct test_wrapper_state
*state
=
901 (struct test_wrapper_state
*)private_data
;
903 torture_comment(state
->tctx
, "fd handler\n");
910 static void test_wrapper_immediate_handler(struct tevent_context
*ev
,
911 struct tevent_immediate
*im
,
914 struct test_wrapper_state
*state
=
915 (struct test_wrapper_state
*)private_data
;
920 torture_comment(state
->tctx
, "immediate handler\n");
924 static void test_wrapper_signal_handler(struct tevent_context
*ev
,
925 struct tevent_signal
*se
,
931 struct test_wrapper_state
*state
=
932 (struct test_wrapper_state
*)private_data
;
934 torture_comment(state
->tctx
, "signal handler\n");
941 static bool test_wrapper(struct torture_context
*tctx
,
942 const void *test_data
)
944 struct test_wrapper_state
*state
= NULL
;
945 int sock
[2] = { -1, -1};
947 const int num_events
= 4;
948 const char *backend
= (const char *)test_data
;
949 struct tevent_context
*ev
= NULL
;
950 struct tevent_context
*wrap_ev
= NULL
;
951 struct tevent_fd
*fde
= NULL
;
952 struct tevent_timer
*te
= NULL
;
953 struct tevent_signal
*se
= NULL
;
954 struct tevent_immediate
*im
= NULL
;
959 ev
= tevent_context_init_byname(tctx
, backend
);
961 torture_skip(tctx
, talloc_asprintf(tctx
,
962 "event backend '%s' not supported\n",
967 tevent_set_debug_stderr(ev
);
968 torture_comment(tctx
, "tevent backend '%s'\n", backend
);
970 wrap_ev
= tevent_context_wrapper_create(
971 ev
, ev
, &test_wrapper_ops
, &state
, struct test_wrapper_state
);
972 torture_assert_not_null_goto(tctx
, wrap_ev
, ok
, done
,
973 "tevent_context_wrapper_create failed\n");
974 *state
= (struct test_wrapper_state
) {
978 ret
= socketpair(AF_UNIX
, SOCK_STREAM
, 0, sock
);
979 torture_assert_goto(tctx
, ret
== 0, ok
, done
, "socketpair failed\n");
981 te
= tevent_add_timer(wrap_ev
, wrap_ev
,
982 timeval_current_ofs(0, 0),
983 test_wrapper_timer_handler
, state
);
984 torture_assert_not_null_goto(tctx
, te
, ok
, done
,
985 "tevent_add_timer failed\n");
987 fde
= tevent_add_fd(wrap_ev
, wrap_ev
,
990 test_wrapper_fd_handler
,
992 torture_assert_not_null_goto(tctx
, fde
, ok
, done
,
993 "tevent_add_fd failed\n");
995 im
= tevent_create_immediate(wrap_ev
);
996 torture_assert_not_null_goto(tctx
, im
, ok
, done
,
997 "tevent_create_immediate failed\n");
999 se
= tevent_add_signal(wrap_ev
, wrap_ev
,
1002 test_wrapper_signal_handler
,
1004 torture_assert_not_null_goto(tctx
, se
, ok
, done
,
1005 "tevent_add_signal failed\n");
1007 do_write(sock
[0], &c
, 1);
1008 kill(getpid(), SIGUSR1
);
1009 tevent_schedule_immediate(im
,
1011 test_wrapper_immediate_handler
,
1014 ret2
= tevent_context_push_use(wrap_ev
);
1015 torture_assert_goto(tctx
, ret2
, ok
, done
, "tevent_context_push_use(wrap_ev) failed\n");
1016 ret2
= tevent_context_push_use(ev
);
1017 torture_assert_goto(tctx
, ret2
, ok
, pop_use
, "tevent_context_push_use(ev) failed\n");
1018 tevent_context_pop_use(ev
);
1019 tevent_context_pop_use(wrap_ev
);
1021 ret
= tevent_loop_wait(ev
);
1022 torture_assert_int_equal_goto(tctx
, ret
, 0, ok
, done
, "tevent_loop_wait failed\n");
1024 torture_comment(tctx
, "Num events: %d\n", state
->num_events
);
1025 torture_comment(tctx
, "Num wrap handlers: %d\n",
1026 state
->num_wrap_handlers
);
1028 torture_assert_int_equal_goto(tctx
, state
->num_events
, num_events
, ok
, done
,
1029 "Wrong event count\n");
1030 torture_assert_int_equal_goto(tctx
, state
->num_wrap_handlers
,
1032 ok
, done
, "Wrong wrapper count\n");
1037 TALLOC_FREE(wrap_ev
);
1040 if (sock
[0] != -1) {
1043 if (sock
[1] != -1) {
1048 tevent_context_pop_use(wrap_ev
);
1052 static void test_free_wrapper_signal_handler(struct tevent_context
*ev
,
1053 struct tevent_signal
*se
,
1059 struct torture_context
*tctx
=
1060 talloc_get_type_abort(private_data
,
1061 struct torture_context
);
1063 torture_comment(tctx
, "signal handler\n");
1068 * signal handlers have highest priority in tevent, so this signal
1069 * handler will always be started before the other handlers
1070 * below. Freeing the (wrapper) event context here tests that the
1071 * wrapper implementation correclty handles the wrapper ev going away
1072 * with pending events.
1078 static void test_free_wrapper_fd_handler(struct tevent_context
*ev
,
1079 struct tevent_fd
*fde
,
1080 unsigned short fd_flags
,
1084 * This should never be called as
1085 * test_free_wrapper_signal_handler()
1086 * already destroyed the wrapper tevent_context.
1091 static void test_free_wrapper_immediate_handler(struct tevent_context
*ev
,
1092 struct tevent_immediate
*im
,
1096 * This should never be called as
1097 * test_free_wrapper_signal_handler()
1098 * already destroyed the wrapper tevent_context.
1103 static void test_free_wrapper_timer_handler(struct tevent_context
*ev
,
1104 struct tevent_timer
*te
,
1109 * This should never be called as
1110 * test_free_wrapper_signal_handler()
1111 * already destroyed the wrapper tevent_context.
1116 static bool test_free_wrapper(struct torture_context
*tctx
,
1117 const void *test_data
)
1119 struct test_wrapper_state
*state
= NULL
;
1120 int sock
[2] = { -1, -1};
1122 const char *backend
= (const char *)test_data
;
1123 TALLOC_CTX
*frame
= talloc_stackframe();
1124 struct tevent_context
*ev
= NULL
;
1125 struct tevent_context
*wrap_ev
= NULL
;
1126 struct tevent_fd
*fde
= NULL
;
1127 struct tevent_timer
*te
= NULL
;
1128 struct tevent_signal
*se
= NULL
;
1129 struct tevent_immediate
*im
= NULL
;
1133 ev
= tevent_context_init_byname(frame
, backend
);
1135 torture_skip(tctx
, talloc_asprintf(tctx
,
1136 "event backend '%s' not supported\n",
1141 tevent_set_debug_stderr(ev
);
1142 torture_comment(tctx
, "tevent backend '%s'\n", backend
);
1144 wrap_ev
= tevent_context_wrapper_create(
1145 ev
, ev
, &test_wrapper_ops
, &state
, struct test_wrapper_state
);
1146 torture_assert_not_null_goto(tctx
, wrap_ev
, ok
, done
,
1147 "tevent_context_wrapper_create failed\n");
1148 *state
= (struct test_wrapper_state
) {
1152 ret
= socketpair(AF_UNIX
, SOCK_STREAM
, 0, sock
);
1153 torture_assert_goto(tctx
, ret
== 0, ok
, done
, "socketpair failed\n");
1155 fde
= tevent_add_fd(wrap_ev
, frame
,
1158 test_free_wrapper_fd_handler
,
1160 torture_assert_not_null_goto(tctx
, fde
, ok
, done
,
1161 "tevent_add_fd failed\n");
1163 te
= tevent_add_timer(wrap_ev
, frame
,
1164 timeval_current_ofs(0, 0),
1165 test_free_wrapper_timer_handler
, NULL
);
1166 torture_assert_not_null_goto(tctx
, te
, ok
, done
,
1167 "tevent_add_timer failed\n");
1169 im
= tevent_create_immediate(frame
);
1170 torture_assert_not_null_goto(tctx
, im
, ok
, done
,
1171 "tevent_create_immediate failed\n");
1173 se
= tevent_add_signal(wrap_ev
, frame
,
1176 test_free_wrapper_signal_handler
,
1178 torture_assert_not_null_goto(tctx
, se
, ok
, done
,
1179 "tevent_add_signal failed\n");
1181 do_write(sock
[0], &c
, 1);
1182 kill(getpid(), SIGUSR1
);
1183 tevent_schedule_immediate(im
,
1185 test_free_wrapper_immediate_handler
,
1188 ret
= tevent_loop_wait(ev
);
1189 torture_assert_goto(tctx
, ret
== 0, ok
, done
, "tevent_loop_wait failed\n");
1196 if (sock
[0] != -1) {
1199 if (sock
[1] != -1) {
1207 static pthread_mutex_t threaded_mutex
= PTHREAD_MUTEX_INITIALIZER
;
1208 static bool do_shutdown
= false;
1210 static void test_event_threaded_lock(void)
1213 ret
= pthread_mutex_lock(&threaded_mutex
);
1217 static void test_event_threaded_unlock(void)
1220 ret
= pthread_mutex_unlock(&threaded_mutex
);
1224 static void test_event_threaded_trace(enum tevent_trace_point point
,
1228 case TEVENT_TRACE_BEFORE_WAIT
:
1229 test_event_threaded_unlock();
1231 case TEVENT_TRACE_AFTER_WAIT
:
1232 test_event_threaded_lock();
1234 case TEVENT_TRACE_BEFORE_LOOP_ONCE
:
1235 case TEVENT_TRACE_AFTER_LOOP_ONCE
:
1240 static void test_event_threaded_timer(struct tevent_context
*ev
,
1241 struct tevent_timer
*te
,
1242 struct timeval current_time
,
1248 static void *test_event_poll_thread(void *private_data
)
1250 struct tevent_context
*ev
= (struct tevent_context
*)private_data
;
1252 test_event_threaded_lock();
1256 ret
= tevent_loop_once(ev
);
1259 test_event_threaded_unlock();
1266 static void test_event_threaded_read_handler(struct tevent_context
*ev
,
1267 struct tevent_fd
*fde
,
1271 int *pfd
= (int *)private_data
;
1275 if ((flags
& TEVENT_FD_READ
) == 0) {
1280 nread
= read(*pfd
, &c
, 1);
1281 } while ((nread
== -1) && (errno
== EINTR
));
1286 static bool test_event_context_threaded(struct torture_context
*test
,
1287 const void *test_data
)
1289 struct tevent_context
*ev
;
1290 struct tevent_timer
*te
;
1291 struct tevent_fd
*fde
;
1292 pthread_t poll_thread
;
1297 ev
= tevent_context_init_byname(test
, "poll_mt");
1298 torture_assert(test
, ev
!= NULL
, "poll_mt not supported");
1300 tevent_set_trace_callback(ev
, test_event_threaded_trace
, NULL
);
1302 te
= tevent_add_timer(ev
, ev
, timeval_current_ofs(5, 0),
1303 test_event_threaded_timer
, NULL
);
1304 torture_assert(test
, te
!= NULL
, "Could not add timer");
1306 ret
= pthread_create(&poll_thread
, NULL
, test_event_poll_thread
, ev
);
1307 torture_assert(test
, ret
== 0, "Could not create poll thread");
1310 torture_assert(test
, ret
== 0, "Could not create pipe");
1314 test_event_threaded_lock();
1316 fde
= tevent_add_fd(ev
, ev
, fds
[0], TEVENT_FD_READ
,
1317 test_event_threaded_read_handler
, &fds
[0]);
1318 torture_assert(test
, fde
!= NULL
, "Could not add fd event");
1320 test_event_threaded_unlock();
1324 do_write(fds
[1], &c
, 1);
1328 test_event_threaded_lock();
1330 test_event_threaded_unlock();
1332 do_write(fds
[1], &c
, 1);
1334 ret
= pthread_join(poll_thread
, NULL
);
1335 torture_assert(test
, ret
== 0, "pthread_join failed");
1340 #define NUM_TEVENT_THREADS 100
1342 /* Ugly, but needed for torture_comment... */
1343 static struct torture_context
*thread_test_ctx
;
1344 static pthread_t thread_map
[NUM_TEVENT_THREADS
];
1345 static unsigned thread_counter
;
1347 /* Called in master thread context */
1348 static void callback_nowait(struct tevent_context
*ev
,
1349 struct tevent_immediate
*im
,
1352 pthread_t
*thread_id_ptr
=
1353 talloc_get_type_abort(private_ptr
, pthread_t
);
1356 for (i
= 0; i
< NUM_TEVENT_THREADS
; i
++) {
1357 if (pthread_equal(*thread_id_ptr
,
1362 torture_comment(thread_test_ctx
,
1363 "Callback %u from thread %u\n",
1369 /* Blast the master tevent_context with a callback, no waiting. */
1370 static void *thread_fn_nowait(void *private_ptr
)
1372 struct tevent_thread_proxy
*master_tp
=
1373 talloc_get_type_abort(private_ptr
, struct tevent_thread_proxy
);
1374 struct tevent_immediate
*im
;
1375 pthread_t
*thread_id_ptr
;
1377 im
= tevent_create_immediate(NULL
);
1381 thread_id_ptr
= talloc(NULL
, pthread_t
);
1382 if (thread_id_ptr
== NULL
) {
1385 *thread_id_ptr
= pthread_self();
1387 tevent_thread_proxy_schedule(master_tp
,
1394 static void timeout_fn(struct tevent_context
*ev
,
1395 struct tevent_timer
*te
,
1396 struct timeval tv
, void *p
)
1398 thread_counter
= NUM_TEVENT_THREADS
* 10;
1401 static bool test_multi_tevent_threaded(struct torture_context
*test
,
1402 const void *test_data
)
1405 struct tevent_context
*master_ev
;
1406 struct tevent_thread_proxy
*tp
;
1408 talloc_disable_null_tracking();
1410 /* Ugly global stuff. */
1411 thread_test_ctx
= test
;
1414 master_ev
= tevent_context_init(NULL
);
1415 if (master_ev
== NULL
) {
1418 tevent_set_debug_stderr(master_ev
);
1420 tp
= tevent_thread_proxy_create(master_ev
);
1423 talloc_asprintf(test
,
1424 "tevent_thread_proxy_create failed\n"));
1425 talloc_free(master_ev
);
1429 for (i
= 0; i
< NUM_TEVENT_THREADS
; i
++) {
1430 int ret
= pthread_create(&thread_map
[i
],
1436 talloc_asprintf(test
,
1437 "Failed to create thread %i, %d\n",
1443 /* Ensure we don't wait more than 10 seconds. */
1444 tevent_add_timer(master_ev
,
1446 timeval_current_ofs(10,0),
1450 while (thread_counter
< NUM_TEVENT_THREADS
) {
1451 int ret
= tevent_loop_once(master_ev
);
1452 torture_assert(test
, ret
== 0, "tevent_loop_once failed");
1455 torture_assert(test
, thread_counter
== NUM_TEVENT_THREADS
,
1456 "thread_counter fail\n");
1458 talloc_free(master_ev
);
1462 struct reply_state
{
1463 struct tevent_thread_proxy
*reply_tp
;
1464 pthread_t thread_id
;
1468 static void thread_timeout_fn(struct tevent_context
*ev
,
1469 struct tevent_timer
*te
,
1470 struct timeval tv
, void *p
)
1472 int *p_finished
= (int *)p
;
1477 /* Called in child-thread context */
1478 static void thread_callback(struct tevent_context
*ev
,
1479 struct tevent_immediate
*im
,
1482 struct reply_state
*rsp
=
1483 talloc_get_type_abort(private_ptr
, struct reply_state
);
1485 talloc_steal(ev
, rsp
);
1486 *rsp
->p_finished
= 1;
1489 /* Called in master thread context */
1490 static void master_callback(struct tevent_context
*ev
,
1491 struct tevent_immediate
*im
,
1494 struct reply_state
*rsp
=
1495 talloc_get_type_abort(private_ptr
, struct reply_state
);
1498 talloc_steal(ev
, rsp
);
1500 for (i
= 0; i
< NUM_TEVENT_THREADS
; i
++) {
1501 if (pthread_equal(rsp
->thread_id
,
1506 torture_comment(thread_test_ctx
,
1507 "Callback %u from thread %u\n",
1510 /* Now reply to the thread ! */
1511 tevent_thread_proxy_schedule(rsp
->reply_tp
,
1519 static void *thread_fn_1(void *private_ptr
)
1521 struct tevent_thread_proxy
*master_tp
=
1522 talloc_get_type_abort(private_ptr
, struct tevent_thread_proxy
);
1523 struct tevent_thread_proxy
*tp
;
1524 struct tevent_immediate
*im
;
1525 struct tevent_context
*ev
;
1526 struct reply_state
*rsp
;
1530 ev
= tevent_context_init(NULL
);
1535 tp
= tevent_thread_proxy_create(ev
);
1541 im
= tevent_create_immediate(ev
);
1547 rsp
= talloc(ev
, struct reply_state
);
1553 rsp
->thread_id
= pthread_self();
1555 rsp
->p_finished
= &finished
;
1557 /* Introduce a little randomness into the mix.. */
1558 usleep(random() % 7000);
1560 tevent_thread_proxy_schedule(master_tp
,
1565 /* Ensure we don't wait more than 10 seconds. */
1566 tevent_add_timer(ev
,
1568 timeval_current_ofs(10,0),
1572 while (finished
== 0) {
1573 ret
= tevent_loop_once(ev
);
1583 * NB. We should talloc_free(ev) here, but if we do
1584 * we currently get hit by helgrind Fix #323432
1585 * "When calling pthread_cond_destroy or pthread_mutex_destroy
1586 * with initializers as argument Helgrind (incorrectly) reports errors."
1588 * http://valgrind.10908.n7.nabble.com/Helgrind-3-9-0-false-positive-
1589 * with-pthread-mutex-destroy-td47757.html
1591 * Helgrind doesn't understand that the request/reply
1592 * messages provide synchronization between the lock/unlock
1593 * in tevent_thread_proxy_schedule(), and the pthread_destroy()
1594 * when the struct tevent_thread_proxy object is talloc_free'd.
1596 * As a work-around for now return ev for the parent thread to free.
1601 static bool test_multi_tevent_threaded_1(struct torture_context
*test
,
1602 const void *test_data
)
1605 struct tevent_context
*master_ev
;
1606 struct tevent_thread_proxy
*master_tp
;
1609 talloc_disable_null_tracking();
1611 /* Ugly global stuff. */
1612 thread_test_ctx
= test
;
1615 master_ev
= tevent_context_init(NULL
);
1616 if (master_ev
== NULL
) {
1619 tevent_set_debug_stderr(master_ev
);
1621 master_tp
= tevent_thread_proxy_create(master_ev
);
1622 if (master_tp
== NULL
) {
1624 talloc_asprintf(test
,
1625 "tevent_thread_proxy_create failed\n"));
1626 talloc_free(master_ev
);
1630 for (i
= 0; i
< NUM_TEVENT_THREADS
; i
++) {
1631 ret
= pthread_create(&thread_map
[i
],
1637 talloc_asprintf(test
,
1638 "Failed to create thread %i, %d\n",
1644 while (thread_counter
< NUM_TEVENT_THREADS
) {
1645 ret
= tevent_loop_once(master_ev
);
1646 torture_assert(test
, ret
== 0, "tevent_loop_once failed");
1649 /* Wait for all the threads to finish - join 'em. */
1650 for (i
= 0; i
< NUM_TEVENT_THREADS
; i
++) {
1652 ret
= pthread_join(thread_map
[i
], &retval
);
1653 torture_assert(test
, ret
== 0, "pthread_join failed");
1654 /* Free the child thread event context. */
1655 talloc_free(retval
);
1658 talloc_free(master_ev
);
1662 struct threaded_test_2
{
1663 struct tevent_threaded_context
*tctx
;
1664 struct tevent_immediate
*im
;
1665 pthread_t thread_id
;
1668 static void master_callback_2(struct tevent_context
*ev
,
1669 struct tevent_immediate
*im
,
1670 void *private_data
);
1672 static void *thread_fn_2(void *private_data
)
1674 struct threaded_test_2
*state
= private_data
;
1676 state
->thread_id
= pthread_self();
1678 usleep(random() % 7000);
1680 tevent_threaded_schedule_immediate(
1681 state
->tctx
, state
->im
, master_callback_2
, state
);
1686 static void master_callback_2(struct tevent_context
*ev
,
1687 struct tevent_immediate
*im
,
1690 struct threaded_test_2
*state
= private_data
;
1693 for (i
= 0; i
< NUM_TEVENT_THREADS
; i
++) {
1694 if (pthread_equal(state
->thread_id
, thread_map
[i
])) {
1698 torture_comment(thread_test_ctx
,
1699 "Callback_2 %u from thread %u\n",
1705 static bool test_multi_tevent_threaded_2(struct torture_context
*test
,
1706 const void *test_data
)
1710 struct tevent_context
*ev
;
1711 struct tevent_threaded_context
*tctx
;
1714 thread_test_ctx
= test
;
1717 ev
= tevent_context_init(test
);
1718 torture_assert(test
, ev
!= NULL
, "tevent_context_init failed");
1721 * tevent_re_initialise used to have a bug where it did not
1722 * re-initialise the thread support after taking it
1723 * down. Exercise that code path.
1725 ret
= tevent_re_initialise(ev
);
1726 torture_assert(test
, ret
== 0, "tevent_re_initialise failed");
1728 tctx
= tevent_threaded_context_create(ev
, ev
);
1729 torture_assert(test
, tctx
!= NULL
,
1730 "tevent_threaded_context_create failed");
1732 for (i
=0; i
<NUM_TEVENT_THREADS
; i
++) {
1733 struct threaded_test_2
*state
;
1735 state
= talloc(ev
, struct threaded_test_2
);
1736 torture_assert(test
, state
!= NULL
, "talloc failed");
1739 state
->im
= tevent_create_immediate(state
);
1740 torture_assert(test
, state
->im
!= NULL
,
1741 "tevent_create_immediate failed");
1743 ret
= pthread_create(&thread_map
[i
], NULL
, thread_fn_2
, state
);
1744 torture_assert(test
, ret
== 0, "pthread_create failed");
1747 while (thread_counter
< NUM_TEVENT_THREADS
) {
1748 ret
= tevent_loop_once(ev
);
1749 torture_assert(test
, ret
== 0, "tevent_loop_once failed");
1752 /* Wait for all the threads to finish - join 'em. */
1753 for (i
= 0; i
< NUM_TEVENT_THREADS
; i
++) {
1755 ret
= pthread_join(thread_map
[i
], &retval
);
1756 torture_assert(test
, ret
== 0, "pthread_join failed");
1757 /* Free the child thread event context. */
1766 struct torture_suite
*torture_local_event(TALLOC_CTX
*mem_ctx
)
1768 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "event");
1769 const char **list
= tevent_backend_list(suite
);
1772 for (i
=0;list
&& list
[i
];i
++) {
1773 struct torture_suite
*backend_suite
;
1775 backend_suite
= torture_suite_create(mem_ctx
, list
[i
]);
1777 torture_suite_add_simple_tcase_const(backend_suite
,
1780 (const void *)list
[i
]);
1781 torture_suite_add_simple_tcase_const(backend_suite
,
1784 (const void *)list
[i
]);
1785 torture_suite_add_simple_tcase_const(backend_suite
,
1788 (const void *)list
[i
]);
1789 torture_suite_add_simple_tcase_const(backend_suite
,
1792 (const void *)list
[i
]);
1793 torture_suite_add_simple_tcase_const(backend_suite
,
1796 (const void *)list
[i
]);
1798 torture_suite_add_suite(suite
, backend_suite
);
1802 torture_suite_add_simple_tcase_const(suite
, "threaded_poll_mt",
1803 test_event_context_threaded
,
1806 torture_suite_add_simple_tcase_const(suite
, "multi_tevent_threaded",
1807 test_multi_tevent_threaded
,
1810 torture_suite_add_simple_tcase_const(suite
, "multi_tevent_threaded_1",
1811 test_multi_tevent_threaded_1
,
1814 torture_suite_add_simple_tcase_const(suite
, "multi_tevent_threaded_2",
1815 test_multi_tevent_threaded_2
,