]> granicus.if.org Git - libevent/commitdiff
Improve testing of when thread-notification occurs
authorNick Mathewson <nickm@torproject.org>
Wed, 8 Sep 2010 17:29:06 +0000 (13:29 -0400)
committerNick Mathewson <nickm@torproject.org>
Wed, 8 Sep 2010 17:29:06 +0000 (13:29 -0400)
test/regress.c
test/regress_thread.c

index 8ce68e77c80da0a1f9e9f0d5d3ac5aa91a380251..a36f6d51ea229b13880ef8e859587c60f3643a6f 100644 (file)
@@ -62,6 +62,7 @@
 #include "event2/buffer_compat.h"
 #include "event2/util.h"
 #include "event-internal.h"
+#include "evthread-internal.h"
 #include "util-internal.h"
 #include "log-internal.h"
 
@@ -805,6 +806,9 @@ test_fork(void)
 
        setup_test("After fork: ");
 
+       tt_assert(current_base);
+       evthread_make_base_notifiable(current_base);
+
        write(pair[0], TEST1, strlen(TEST1)+1);
 
        event_set(&ev, pair[1], EV_READ, simple_read_cb, &ev);
@@ -863,6 +867,7 @@ test_fork(void)
 
        evsignal_del(&sig_ev);
 
+       end:
        cleanup_test();
 }
 
index 34cf64b1599b6ecf0ed19b557f554b8b89318cc3..88b0e167bb8cf23f30b031f2144a5506ed76816b 100644 (file)
 #include <process.h>
 #endif
 #include <assert.h>
+#ifdef _EVENT_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "sys/queue.h"
 
 #include "event2/util.h"
 #include "event2/event.h"
 #include "event2/event_struct.h"
 #include "event2/thread.h"
 #include "evthread-internal.h"
+#include "event-internal.h"
 #include "regress.h"
 #include "tinytest_macros.h"
 
@@ -131,7 +137,7 @@ basic_thread(void *arg)
 
        /* exit the loop only if all threads fired all timeouts */
        EVLOCK_LOCK(count_lock, 0);
-       if (count >= NUM_THREADS * 100)
+       if (count >= NUM_THREADS * NUM_ITERATIONS)
                event_base_loopexit(base, NULL);
        EVLOCK_UNLOCK(count_lock, 0);
 
@@ -141,6 +147,27 @@ basic_thread(void *arg)
        THREAD_RETURN();
 }
 
+static int got_sigchld = 0;
+static void
+sigchld_cb(evutil_socket_t fd, short event, void *arg)
+{
+       struct timeval tv;
+       struct event_base *base = arg;
+
+       got_sigchld++;
+       tv.tv_usec = 100000;
+       tv.tv_sec = 0;
+       event_base_loopexit(base, &tv);
+}
+
+
+static int notification_fd_used = 0;
+static void
+notify_fd_cb(evutil_socket_t fd, short event, void *arg)
+{
+       ++notification_fd_used;
+}
+
 static void
 thread_basic(void *arg)
 {
@@ -151,6 +178,10 @@ thread_basic(void *arg)
        struct basic_test_data *data = arg;
        struct event_base *base = data->base;
 
+       int forking = data->setup_data && !strcmp(data->setup_data, "forking");
+       struct event *notification_event = NULL;
+       struct event *sigchld_event = NULL;
+
        EVTHREAD_ALLOC_LOCK(count_lock, 0);
        tt_assert(count_lock);
 
@@ -159,6 +190,42 @@ thread_basic(void *arg)
                tt_abort_msg("Couldn't make base notifiable!");
        }
 
+#ifndef WIN32
+       if (forking) {
+               pid_t pid;
+               int status;
+               sigchld_event = evsignal_new(base, SIGCHLD, sigchld_cb, base);
+               /* This piggybacks on the th_notify_fd weirdly, and looks
+                * inside libevent internals.  Not a good idea in non-testing
+                * code! */
+               notification_event = event_new(base,
+                   base->th_notify_fd[0], EV_READ|EV_PERSIST, notify_fd_cb,
+                   NULL);
+               event_add(sigchld_event, NULL);
+               event_add(notification_event, NULL);
+
+               if ((pid = fork()) == 0) {
+                       if (event_reinit(base) < 0) {
+                               TT_FAIL(("reinit"));
+                               exit(1);
+                       }
+                       goto child;
+               }
+
+               event_base_dispatch(base);
+
+               if (waitpid(pid, &status, 0) == -1)
+                       tt_abort_perror("waitpid");
+               TT_BLATHER(("Waitpid okay\n"));
+
+               tt_assert(got_sigchld);
+               tt_int_op(notification_fd_used, ==, 0);
+
+               goto end;
+       }
+
+child:
+#endif
        for (i = 0; i < NUM_THREADS; ++i)
                THREAD_START(threads[i], basic_thread, base);
 
@@ -177,8 +244,15 @@ thread_basic(void *arg)
        tt_int_op(count, ==, NUM_THREADS * NUM_ITERATIONS);
 
        EVTHREAD_FREE_LOCK(count_lock, 0);
+
+       TT_BLATHER(("notifiations==%d", notification_fd_used));
+
 end:
-       ;
+
+       if (notification_event)
+               event_free(notification_event);
+       if (sigchld_event)
+               event_free(sigchld_event);
 }
 
 #undef NUM_THREADS
@@ -313,10 +387,16 @@ end:
 }
 
 #define TEST(name)                                                     \
-           { #name, thread_##name, TT_FORK|TT_NEED_THREADS|TT_NEED_BASE, \
-             &basic_setup, NULL }
+       { #name, thread_##name, TT_FORK|TT_NEED_THREADS|TT_NEED_BASE,   \
+         &basic_setup, NULL }
+
 struct testcase_t thread_testcases[] = {
-       TEST(basic),
+       { "basic", thread_basic, TT_FORK|TT_NEED_THREADS|TT_NEED_BASE,
+         &basic_setup, NULL },
+#ifndef WIN32
+       { "forking", thread_basic, TT_FORK|TT_NEED_THREADS|TT_NEED_BASE,
+         &basic_setup, (char*)"forking" },
+#endif
        TEST(conditions_simple),
        END_OF_TESTCASES
 };