From 908e710d40fb30cc68b515cce435a026c7ecc62a Mon Sep 17 00:00:00 2001 From: Azat Khuzhin Date: Tue, 13 Nov 2018 21:31:44 +0300 Subject: [PATCH] bev_async: trigger/run only deferred callbacks Otherwise callbacks will be runned even without event_loop, due to nature of IOCP. A simple example is: evhttp_connection_free(client) # freeing the client will trigger evhttp_connection_free() for the # client on the server side, and hence there will double free evhttp_free(server) Fixes: iocp/http/simple --- bufferevent_async.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/bufferevent_async.c b/bufferevent_async.c index 63ff7c37..d2eefed4 100644 --- a/bufferevent_async.c +++ b/bufferevent_async.c @@ -100,6 +100,14 @@ const struct bufferevent_ops bufferevent_ops_async = { be_async_ctrl, }; +static inline void +be_async_run_eventcb(struct bufferevent *bev, short what, int options) +{ bufferevent_run_eventcb_(bev, what, options|BEV_TRIG_DEFER_CALLBACKS); } + +static inline void +be_async_trigger_nolock(struct bufferevent *bev, short what, int options) +{ bufferevent_trigger_nolock_(bev, what, options|BEV_TRIG_DEFER_CALLBACKS); } + static inline int fatal_error(int err) { @@ -230,7 +238,7 @@ bev_async_consider_writing(struct bufferevent_async *beva) &beva->write_overlapped)) { bufferevent_decref_(bev); beva->ok = 0; - bufferevent_run_eventcb_(bev, BEV_EVENT_ERROR, 0); + be_async_run_eventcb(bev, BEV_EVENT_ERROR, 0); } else { beva->write_in_progress = at_most; bufferevent_decrement_write_buckets_(&beva->bev, at_most); @@ -283,7 +291,7 @@ bev_async_consider_reading(struct bufferevent_async *beva) bufferevent_incref_(bev); if (evbuffer_launch_read_(bev->input, at_most, &beva->read_overlapped)) { beva->ok = 0; - bufferevent_run_eventcb_(bev, BEV_EVENT_ERROR, 0); + be_async_run_eventcb(bev, BEV_EVENT_ERROR, 0); bufferevent_decref_(bev); } else { beva->read_in_progress = at_most; @@ -441,8 +449,7 @@ connect_complete(struct event_overlapped *eo, ev_uintptr_t key, else bev_async_set_wsa_error(bev, eo); - bufferevent_run_eventcb_(bev, - ok? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR, 0); + be_async_run_eventcb(bev, ok ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR, 0); event_base_del_virtual_(bev->ev_base); @@ -472,16 +479,16 @@ read_complete(struct event_overlapped *eo, ev_uintptr_t key, if (bev_a->ok) { if (ok && nbytes) { BEV_RESET_GENERIC_READ_TIMEOUT(bev); - bufferevent_trigger_nolock_(bev, EV_READ, 0); + be_async_trigger_nolock(bev, EV_READ, 0); bev_async_consider_reading(bev_a); } else if (!ok) { what |= BEV_EVENT_ERROR; bev_a->ok = 0; - bufferevent_run_eventcb_(bev, what, 0); + be_async_run_eventcb(bev, what, 0); } else if (!nbytes) { what |= BEV_EVENT_EOF; bev_a->ok = 0; - bufferevent_run_eventcb_(bev, what, 0); + be_async_run_eventcb(bev, what, 0); } } @@ -515,16 +522,16 @@ write_complete(struct event_overlapped *eo, ev_uintptr_t key, if (bev_a->ok) { if (ok && nbytes) { BEV_RESET_GENERIC_WRITE_TIMEOUT(bev); - bufferevent_trigger_nolock_(bev, EV_WRITE, 0); + be_async_trigger_nolock(bev, EV_WRITE, 0); bev_async_consider_writing(bev_a); } else if (!ok) { what |= BEV_EVENT_ERROR; bev_a->ok = 0; - bufferevent_run_eventcb_(bev, what, 0); + be_async_run_eventcb(bev, what, 0); } else if (!nbytes) { what |= BEV_EVENT_EOF; bev_a->ok = 0; - bufferevent_run_eventcb_(bev, what, 0); + be_async_run_eventcb(bev, what, 0); } } -- 2.40.0