mirror of
https://github.com/libevent/libevent.git
synced 2025-01-31 09:12:55 +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,9 +425,16 @@ 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);
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
|
||||||
if (bevf->got_eof)
|
if (bevf->got_eof)
|
||||||
state = BEV_FINISHED;
|
state = BEV_FINISHED;
|
||||||
@ -443,8 +450,9 @@ be_filter_readcb(struct bufferevent *underlying, void *me_)
|
|||||||
* force readcb calls as needed. */
|
* force readcb calls as needed. */
|
||||||
if (processed_any)
|
if (processed_any)
|
||||||
bufferevent_trigger_nolock_(bufev, EV_READ, 0);
|
bufferevent_trigger_nolock_(bufev, EV_READ, 0);
|
||||||
|
}
|
||||||
|
|
||||||
bufferevent_decref_and_unlock_(bufev);
|
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);
|
||||||
|
|
||||||
|
// 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);
|
be_filter_process_output(bevf, BEV_NORMAL, &processed_any);
|
||||||
bufferevent_decref_and_unlock_(bev);
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
BEV_LOCK(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) {
|
||||||
|
|
||||||
bufferevent_incref_and_lock_(bev);
|
|
||||||
/* All we can really to is tell our own eventcb. */
|
/* All we can really to is tell our own eventcb. */
|
||||||
bufferevent_run_eventcb_(bev, what, 0);
|
bufferevent_run_eventcb_(bev, what, 0);
|
||||||
bufferevent_decref_and_unlock_(bev);
|
}
|
||||||
|
|
||||||
|
BEV_UNLOCK(bev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
Loading…
x
Reference in New Issue
Block a user