/* * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ #include"../util-internal.h" #include"event2/event-config.h"
/* On Linux 3.2.1 (at least, as patched by Fedora and tested by Nick), * doing a "recv" on an AF_UNIX socket resets the readability of the * socket, even though there is no state change, so we don't actually * get edge-triggered behavior. Yuck! Linux 3.1.9 didn't have this * problem.
*/
supports_et = base_supports_et(base);
TT_BLATHER(("Checking for edge-triggered events with %s, which should %s" "support edge-triggering", event_base_get_method(base),
supports_et?"":"not "));
/* Initialize one event */
ev = event_new(base, pair[1], EV_READ|EV_ET|EV_PERSIST, read_cb, &ev);
tt_assert(ev != NULL);
tt_int_op(event_add(ev, NULL), ==, 0);
/* We're going to call the dispatch function twice. The first invocation * will read a single byte from pair[1] in either case. If we're edge * triggered, we'll only see the event once (since we only see transitions * from no data to data), so the second invocation of event_base_loop will * do nothing. If we're level triggered, the second invocation of * event_base_loop will also activate the event (because there's still
* data to read). */
tt_int_op(event_base_loop(base,EVLOOP_NONBLOCK|EVLOOP_ONCE), ==, 0);
tt_int_op(event_base_loop(base,EVLOOP_NONBLOCK|EVLOOP_ONCE), ==, 0);
/* After two or more events have been registered for the same * file descriptor using EV_ET, if one of the events is * deleted, then the epoll_ctl() call issued by libevent drops * the EPOLLET flag resulting in level triggered * notifications.
*/ staticvoid
test_edge_triggered_multiple_events(void *data_)
{ struct basic_test_data *data = data_; struct event *read_ev = NULL; struct event *write_ev = NULL; constchar c = 'A'; struct event_base *base = data->base;
evutil_socket_t *pair = data->pair;
if (!base_supports_et(base)) {
tt_skip(); return;
}
/* trigger acitivity second time for the backend that can have multiple
* events for one fd (like kqueue) */
close(pair[0]);
pair[0] = -1;
/* Verify that we are still edge-triggered for write notifications */
event_base_loop(base, EVLOOP_NONBLOCK|EVLOOP_ONCE);
event_base_loop(base, EVLOOP_NONBLOCK|EVLOOP_ONCE);
tt_assert(last_write_notification_was_et);
tt_int_op(write_notification_count, ==, 2);
end: if (read_ev)
event_free(read_ev); if (write_ev)
event_free(write_ev);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.