mirror of
https://github.com/libevent/libevent.git
synced 2025-01-09 00:56:20 +08:00
Fix issue #127, double free for filterevents that use BEV_OPT_CLOSE_ON_FREE
This commit is contained in:
parent
571295bdf8
commit
2c82aa0fef
@ -425,26 +425,34 @@ be_filter_readcb(struct bufferevent *underlying, void *me_)
|
|||||||
enum bufferevent_filter_result res;
|
enum bufferevent_filter_result res;
|
||||||
enum bufferevent_flush_mode state;
|
enum bufferevent_flush_mode state;
|
||||||
struct bufferevent *bufev = downcast(bevf);
|
struct bufferevent *bufev = downcast(bevf);
|
||||||
|
struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
|
||||||
int processed_any = 0;
|
int processed_any = 0;
|
||||||
|
|
||||||
bufferevent_incref_and_lock_(bufev);
|
BEV_LOCK(bufev);
|
||||||
|
|
||||||
if (bevf->got_eof)
|
// It's possible our refcount is 0 at this point if another thread free'd our filterevent
|
||||||
state = BEV_FINISHED;
|
EVUTIL_ASSERT(bufev_private->refcnt >= 0);
|
||||||
else
|
|
||||||
state = BEV_NORMAL;
|
|
||||||
|
|
||||||
/* XXXX use return value */
|
// If our refcount is > 0
|
||||||
res = be_filter_process_input(bevf, state, &processed_any);
|
if (bufev_private->refcnt > 0) {
|
||||||
(void)res;
|
|
||||||
|
|
||||||
/* XXX This should be in process_input, not here. There are
|
if (bevf->got_eof)
|
||||||
* other places that can call process-input, and they should
|
state = BEV_FINISHED;
|
||||||
* force readcb calls as needed. */
|
else
|
||||||
if (processed_any)
|
state = BEV_NORMAL;
|
||||||
bufferevent_trigger_nolock_(bufev, EV_READ, 0);
|
|
||||||
|
|
||||||
bufferevent_decref_and_unlock_(bufev);
|
/* XXXX use return value */
|
||||||
|
res = be_filter_process_input(bevf, state, &processed_any);
|
||||||
|
(void)res;
|
||||||
|
|
||||||
|
/* XXX This should be in process_input, not here. There are
|
||||||
|
* other places that can call process-input, and they should
|
||||||
|
* force readcb calls as needed. */
|
||||||
|
if (processed_any)
|
||||||
|
bufferevent_trigger_nolock_(bufev, EV_READ, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BEV_UNLOCK(bufev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called when the underlying socket has drained enough that we can write to
|
/* Called when the underlying socket has drained enough that we can write to
|
||||||
@ -454,11 +462,20 @@ be_filter_writecb(struct bufferevent *underlying, void *me_)
|
|||||||
{
|
{
|
||||||
struct bufferevent_filtered *bevf = me_;
|
struct bufferevent_filtered *bevf = me_;
|
||||||
struct bufferevent *bev = downcast(bevf);
|
struct bufferevent *bev = downcast(bevf);
|
||||||
|
struct bufferevent_private *bufev_private = BEV_UPCAST(bev);
|
||||||
int processed_any = 0;
|
int processed_any = 0;
|
||||||
|
|
||||||
bufferevent_incref_and_lock_(bev);
|
BEV_LOCK(bev);
|
||||||
be_filter_process_output(bevf, BEV_NORMAL, &processed_any);
|
|
||||||
bufferevent_decref_and_unlock_(bev);
|
// It's possible our refcount is 0 at this point if another thread free'd our filterevent
|
||||||
|
EVUTIL_ASSERT(bufev_private->refcnt >= 0);
|
||||||
|
|
||||||
|
// If our refcount is > 0
|
||||||
|
if (bufev_private->refcnt > 0) {
|
||||||
|
be_filter_process_output(bevf, BEV_NORMAL, &processed_any);
|
||||||
|
}
|
||||||
|
|
||||||
|
BEV_UNLOCK(bev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called when the underlying socket has given us an error */
|
/* Called when the underlying socket has given us an error */
|
||||||
@ -467,11 +484,21 @@ be_filter_eventcb(struct bufferevent *underlying, short what, void *me_)
|
|||||||
{
|
{
|
||||||
struct bufferevent_filtered *bevf = me_;
|
struct bufferevent_filtered *bevf = me_;
|
||||||
struct bufferevent *bev = downcast(bevf);
|
struct bufferevent *bev = downcast(bevf);
|
||||||
|
struct bufferevent_private *bufev_private = BEV_UPCAST(bev);
|
||||||
|
|
||||||
bufferevent_incref_and_lock_(bev);
|
BEV_LOCK(bev);
|
||||||
/* All we can really to is tell our own eventcb. */
|
|
||||||
bufferevent_run_eventcb_(bev, what, 0);
|
// It's possible our refcount is 0 at this point if another thread free'd our filterevent
|
||||||
bufferevent_decref_and_unlock_(bev);
|
EVUTIL_ASSERT(bufev_private->refcnt >= 0);
|
||||||
|
|
||||||
|
// If our refcount is > 0
|
||||||
|
if (bufev_private->refcnt > 0) {
|
||||||
|
|
||||||
|
/* All we can really to is tell our own eventcb. */
|
||||||
|
bufferevent_run_eventcb_(bev, what, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BEV_UNLOCK(bev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
Loading…
x
Reference in New Issue
Block a user