mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-09 12:28:19 -04:00
Fix bufferevent_pair to properly set BEV_EVENT_{READING,WRITING} on flush.
Here's some fun. From `bufferevent.h`: ``` #define BEV_EVENT_READING 0x01 /**< error encountered while reading */ #define BEV_EVENT_WRITING 0x02 /**< error encountered while writing */ ``` And from `event.h`: ``` /** Wait for a socket or FD to become readable */ #define EV_READ 0x02 /** Wait for a socket or FD to become writeable */ #define EV_WRITE 0x04 ``` Library users have to be very careful to get this right; it turns out, the library itself got this wrong in the `bufferevent_pair` code. It appears that in most of the code, only `BEV_EVENT_FINISHED` will indicate whether it's read or write; on error or timeout, it appears that "both" is assumed and not set in the callback. I read through all the other places where `BEV_EVENT_FINISHED` is passed to an event callback; it appears that the pair code is the only spot that got it wrong. azat: add TT_FORK to avoid breaking clean env, and rebase commit message (copied from #359) Fixes: #359
This commit is contained in:
parent
2a4bf29470
commit
285188963d
@ -325,7 +325,12 @@ be_pair_flush(struct bufferevent *bev, short iotype,
|
|||||||
be_pair_transfer(bev, partner, 1);
|
be_pair_transfer(bev, partner, 1);
|
||||||
|
|
||||||
if (mode == BEV_FINISHED) {
|
if (mode == BEV_FINISHED) {
|
||||||
bufferevent_run_eventcb_(partner, iotype|BEV_EVENT_EOF, 0);
|
short what = BEV_EVENT_EOF;
|
||||||
|
if (iotype & EV_READ)
|
||||||
|
what |= BEV_EVENT_WRITING;
|
||||||
|
if (iotype & EV_WRITE)
|
||||||
|
what |= BEV_EVENT_READING;
|
||||||
|
bufferevent_run_eventcb_(partner, what, 0);
|
||||||
}
|
}
|
||||||
decref_and_unlock(bev);
|
decref_and_unlock(bev);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1190,6 +1190,42 @@ end:
|
|||||||
bufferevent_free(bev);
|
bufferevent_free(bev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pair_flush_eventcb(struct bufferevent *bev, short what, void *ctx)
|
||||||
|
{
|
||||||
|
int *callback_what = ctx;
|
||||||
|
*callback_what = what;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_bufferevent_pair_flush(void *arg)
|
||||||
|
{
|
||||||
|
struct basic_test_data *data = arg;
|
||||||
|
struct bufferevent *pair[2];
|
||||||
|
struct bufferevent *bev1 = NULL;
|
||||||
|
struct bufferevent *bev2 = NULL;
|
||||||
|
int callback_what = 0;
|
||||||
|
|
||||||
|
tt_assert(0 == bufferevent_pair_new(data->base, 0, pair));
|
||||||
|
bev1 = pair[0];
|
||||||
|
bev2 = pair[1];
|
||||||
|
tt_assert(0 == bufferevent_enable(bev1, EV_WRITE));
|
||||||
|
tt_assert(0 == bufferevent_enable(bev2, EV_READ));
|
||||||
|
|
||||||
|
bufferevent_setcb(bev2, NULL, NULL, pair_flush_eventcb, &callback_what);
|
||||||
|
|
||||||
|
bufferevent_flush(bev1, EV_WRITE, BEV_FINISHED);
|
||||||
|
|
||||||
|
event_base_loop(data->base, EVLOOP_ONCE);
|
||||||
|
|
||||||
|
tt_assert(callback_what == (BEV_EVENT_READING | BEV_EVENT_EOF));
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (bev1)
|
||||||
|
bufferevent_free(bev1);
|
||||||
|
if (bev2)
|
||||||
|
bufferevent_free(bev2);
|
||||||
|
}
|
||||||
|
|
||||||
struct testcase_t bufferevent_testcases[] = {
|
struct testcase_t bufferevent_testcases[] = {
|
||||||
|
|
||||||
@ -1260,6 +1296,9 @@ struct testcase_t bufferevent_testcases[] = {
|
|||||||
{ "bufferevent_socket_filter_inactive",
|
{ "bufferevent_socket_filter_inactive",
|
||||||
test_bufferevent_socket_filter_inactive,
|
test_bufferevent_socket_filter_inactive,
|
||||||
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
|
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
|
||||||
|
{ "bufferevent_pair_flush",
|
||||||
|
test_bufferevent_pair_flush,
|
||||||
|
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
|
||||||
|
|
||||||
END_OF_TESTCASES,
|
END_OF_TESTCASES,
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user