]> granicus.if.org Git - libevent/commitdiff
Make debug mode catch mixed ET and non-ET events on an fd
authorNick Mathewson <nickm@torproject.org>
Wed, 28 Apr 2010 15:51:56 +0000 (11:51 -0400)
committerNick Mathewson <nickm@torproject.org>
Wed, 28 Apr 2010 16:20:18 +0000 (12:20 -0400)
Of the backends that support edge-triggered IO, most (all?) do not
support attempts to mix edge-triggered and level-triggered IO on the
same FD.  With debugging mode enabled, we now detect and refuse attempts
to add a level-triggered IO event to an fd that already has an
edge-triggered IO event, and vice versa.

event-internal.h
evmap.c
test/regress_et.c

index f9de18ad3f3837ed20d1930513ac44ec4918e713..7388a5975b07312e5f92be1d877274462a5c8c32 100644 (file)
@@ -158,6 +158,9 @@ struct event_changelist {
 #ifndef _EVENT_DISABLE_DEBUG_MODE
 /* Global internal flag: set to one if debug mode is on. */
 extern int _event_debug_mode_on;
+#define EVENT_DEBUG_MODE_IS_ON() (_event_debug_mode_on)
+#else
+#define EVENT_DEBUG_MODE_IS_ON() (0)
 #endif
 
 struct event_base {
diff --git a/evmap.c b/evmap.c
index b11ec3c91b5005b928d4342bf418b331827419ae..cb28002a4295f8ed95e560014f3c6c6e65371fd5 100644 (file)
--- a/evmap.c
+++ b/evmap.c
@@ -264,6 +264,7 @@ evmap_io_add(struct event_base *base, evutil_socket_t fd, struct event *ev)
        struct evmap_io *ctx = NULL;
        int nread, nwrite, retval = 0;
        short res = 0, old = 0;
+       struct event *old_ev;
 
        EVUTIL_ASSERT(fd == ev->ev_fd);
 
@@ -300,6 +301,13 @@ evmap_io_add(struct event_base *base, evutil_socket_t fd, struct event *ev)
                    (int)fd);
                return -1;
        }
+       if (EVENT_DEBUG_MODE_IS_ON() &&
+           (old_ev = TAILQ_FIRST(&ctx->events)) &&
+           (old_ev->ev_events&EV_ET) != (ev->ev_events&EV_ET)) {
+               event_warnx("Tried to mix edge-triggered and non-edge-triggered"
+                   " events on fd %d", (int)fd);
+               return -1;
+       }
 
        if (res) {
                void *extra = ((char*)ctx) + sizeof(struct evmap_io);
index 98f3dcf23777d35c20096c8c3ac50b4e6c422cfe..87ecc5baca1864e4ab89aa237fa98cda80b19a09 100644 (file)
@@ -149,7 +149,49 @@ test_edgetriggered(void *et)
        evutil_closesocket(pair[1]);
 }
 
+static void
+test_edgetriggered_mix_error(void *data_)
+{
+       struct basic_test_data *data = data_;
+       struct event_base *base;
+       struct event *ev_et=NULL, *ev_lt=NULL;
+
+#ifdef _EVENT_DISABLE_DEBUG_MODE
+       if (1)
+               tt_skip();
+#endif
+
+       event_enable_debug_mode();
+
+       base = event_base_new();
+
+       /* try mixing edge-triggered and level-triggered to make sure it fails*/
+       ev_et = event_new(base, data->pair[0], EV_READ|EV_ET, read_cb, ev_et);
+       ev_lt = event_new(base, data->pair[0], EV_READ, read_cb, ev_lt);
+
+       /* Add edge-triggered, then level-triggered.  Get an error. */
+       tt_int_op(0, ==, event_add(ev_et, NULL));
+       tt_int_op(-1, ==, event_add(ev_lt, NULL));
+       tt_int_op(EV_READ, ==, event_pending(ev_et, EV_READ, NULL));
+       tt_int_op(0, ==, event_pending(ev_lt, EV_READ, NULL));
+
+       tt_int_op(0, ==, event_del(ev_et));
+       /* Add level-triggered, then edge-triggered.  Get an error. */
+       tt_int_op(0, ==, event_add(ev_lt, NULL));
+       tt_int_op(-1, ==, event_add(ev_et, NULL));
+       tt_int_op(EV_READ, ==, event_pending(ev_lt, EV_READ, NULL));
+       tt_int_op(0, ==, event_pending(ev_et, EV_READ, NULL));
+
+end:
+       if (ev_et)
+               event_free(ev_et);
+       if (ev_lt)
+               event_free(ev_lt);
+}
+
 struct testcase_t edgetriggered_testcases[] = {
        { "et", test_edgetriggered, TT_FORK, NULL, NULL },
+       { "et_mix_error", test_edgetriggered_mix_error,
+         TT_FORK|TT_NEED_SOCKETPAIR|TT_NO_LOGS, &basic_setup, NULL },
        END_OF_TESTCASES
 };