void event_base_add_virtual(struct event_base *base);
void event_base_del_virtual(struct event_base *base);
+/** For debugging: unless assertions are disabled, verify the referential
+ integrity of the internal data structures of 'base'. This operation can
+ be expensive.
+
+ Returns on success; aborts on failure.
+*/
+void event_base_assert_ok(struct event_base *base);
+
#ifdef __cplusplus
}
#endif
return 0;
}
#endif
+
+void
+event_base_assert_ok(struct event_base *base)
+{
+ int i;
+ EVBASE_ACQUIRE_LOCK(base, th_base_lock);
+ evmap_check_integrity(base);
+
+ /* Check the heap property */
+ for (i = 1; i < (int)base->timeheap.n; ++i) {
+ int parent = (i - 1) / 2;
+ struct event *ev, *p_ev;
+ ev = base->timeheap.p[i];
+ p_ev = base->timeheap.p[parent];
+ EVUTIL_ASSERT(ev->ev_flags & EV_TIMEOUT);
+ EVUTIL_ASSERT(evutil_timercmp(&p_ev->ev_timeout, &ev->ev_timeout, <=));
+ EVUTIL_ASSERT(ev->ev_timeout_pos.min_heap_idx == i);
+ }
+
+ /* Check that the common timeouts are fine */
+ for (i = 0; i < base->n_common_timeouts; ++i) {
+ struct common_timeout_list *ctl = base->common_timeout_queues[i];
+ struct event *last=NULL, *ev;
+ TAILQ_FOREACH(ev, &ctl->events, ev_timeout_pos.ev_next_with_common_timeout) {
+ if (last)
+ EVUTIL_ASSERT(evutil_timercmp(&last->ev_timeout, &ev->ev_timeout, <=));
+ EVUTIL_ASSERT(ev->ev_flags & EV_TIMEOUT);
+ EVUTIL_ASSERT(is_common_timeout(&ev->ev_timeout,base));
+ EVUTIL_ASSERT(COMMON_TIMEOUT_IDX(&ev->ev_timeout) == i);
+ last = ev;
+ }
+ }
+
+ EVBASE_RELEASE_LOCK(base, th_base_lock);
+}
void *evmap_io_get_fdinfo(struct event_io_map *ctx, evutil_socket_t fd);
+void evmap_check_integrity(struct event_base *base);
+
#endif /* _EVMAP_H_ */
return (0);
}
+void
+evmap_check_integrity(struct event_base *base)
+{
+#define EVLIST_X_SIGFOUND 0x1000
+#define EVLIST_X_IOFOUND 0x2000
+
+ int i;
+ struct event *ev;
+ struct event_io_map *io = &base->io;
+ struct event_signal_map *sigmap = &base->sigmap;
+ int nsignals, ntimers, nio;
+ nsignals = ntimers = nio = 0;
+
+ TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
+ EVUTIL_ASSERT(ev->ev_flags & EVLIST_INSERTED);
+ EVUTIL_ASSERT(ev->ev_flags & EVLIST_INIT);
+ ev->ev_flags &= ~(EVLIST_X_SIGFOUND|EVLIST_X_IOFOUND);
+ }
+
+
+ for (i = 0; i < io->nentries; ++i) {
+ struct evmap_io *ctx = io->entries[i];
+ if (!ctx)
+ continue;
+
+ TAILQ_FOREACH(ev, &ctx->events, ev_io_next) {
+ EVUTIL_ASSERT(!(ev->ev_flags & EVLIST_X_IOFOUND));
+ EVUTIL_ASSERT(ev->ev_fd == i);
+ ev->ev_flags |= EVLIST_X_IOFOUND;
+ nio++;
+ }
+ }
+
+ for (i = 0; i < sigmap->nentries; ++i) {
+ struct evmap_signal *ctx = sigmap->entries[i];
+ if (!ctx)
+ continue;
+
+ TAILQ_FOREACH(ev, &ctx->events, ev_signal_next) {
+ EVUTIL_ASSERT(!(ev->ev_flags & EVLIST_X_SIGFOUND));
+ EVUTIL_ASSERT(ev->ev_fd == i);
+ ev->ev_flags |= EVLIST_X_SIGFOUND;
+ nsignals++;
+ }
+ }
+
+ TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
+ if (ev->ev_events & (EV_READ|EV_WRITE)) {
+ EVUTIL_ASSERT(ev->ev_flags & EVLIST_X_IOFOUND);
+ --nio;
+ }
+ if (ev->ev_events & EV_SIGNAL) {
+ EVUTIL_ASSERT(ev->ev_flags & EVLIST_X_SIGFOUND);
+ --nsignals;
+ }
+ }
+
+ EVUTIL_ASSERT(nio == 0);
+ EVUTIL_ASSERT(nsignals == 0);
+ /* There is no "EVUTIL_ASSERT(ntimers == 0)": eventqueue is only for
+ * pending signals and io events.
+ */
+}
tv_exit.tv_usec = 600 * 1000;
event_base_loopexit(base, &tv_exit);
+ event_base_assert_ok(base);
evutil_gettimeofday(&start, NULL);
event_base_dispatch(base);
+ event_base_assert_ok(base);
tt_int_op(res.n, ==, 3);
tt_int_op(res.events[0], ==, EV_READ);
}
}
+ event_base_assert_ok(base);
event_base_dispatch(base);
evutil_gettimeofday(&now, NULL);
+ event_base_assert_ok(base);
for (i=0; i<10; ++i) {
struct timeval tmp;
evsignal_set(&sig_ev, SIGCHLD, child_signal_cb, &got_sigchld);
evsignal_add(&sig_ev, NULL);
+ event_base_assert_ok(current_base);
+ TT_BLATHER(("Before fork"));
if ((pid = fork()) == 0) {
/* in the child */
+ TT_BLATHER(("In child, before reinit"));
+ event_base_assert_ok(current_base);
if (event_reinit(current_base) == -1) {
fprintf(stdout, "FAILED (reinit)\n");
exit(1);
}
+ TT_BLATHER(("After reinit"));
+ event_base_assert_ok(current_base);
+ TT_BLATHER(("After assert-ok"));
evsignal_del(&sig_ev);
tt_fail_perror("write");
}
+ TT_BLATHER(("Before waitpid"));
if (waitpid(pid, &status, 0) == -1) {
fprintf(stdout, "FAILED (fork)\n");
exit(1);
}
+ TT_BLATHER(("After waitpid"));
if (WEXITSTATUS(status) != 76) {
fprintf(stdout, "FAILED (exit): %d\n", WEXITSTATUS(status));