mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-11 05:14:46 -04:00
Fix a segfault when freeing SSL bufferevents in an unusual order
Have container bufferevents hold a reference to their underlying bufferevents. (Commit message and minor revisions by nickm.)
This commit is contained in:
parent
a6adeca72c
commit
a773df54ce
@ -217,6 +217,8 @@ void _bufferevent_incref_and_lock(struct bufferevent *bufev);
|
||||
/** Internal: Drop the reference count on bufev, freeing as necessary, and
|
||||
* unlocking it otherwise. */
|
||||
void _bufferevent_decref_and_unlock(struct bufferevent *bufev);
|
||||
/** Sometimes it is more clear to say "decref" than "free" */
|
||||
#define bufferevent_decref(b) bufferevent_free(b)
|
||||
|
||||
/** Internal: If callbacks are deferred and we have a read callback, schedule
|
||||
* a readcb. Otherwise just run the readcb. */
|
||||
|
@ -512,12 +512,15 @@ _bufferevent_decref_and_unlock(struct bufferevent *bufev)
|
||||
{
|
||||
struct bufferevent_private *bufev_private =
|
||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||
struct bufferevent *underlying;
|
||||
|
||||
if (--bufev_private->refcnt) {
|
||||
BEV_UNLOCK(bufev);
|
||||
return;
|
||||
}
|
||||
|
||||
underlying = bufferevent_get_underlying(bufev);
|
||||
|
||||
/* Clean up the shared info */
|
||||
if (bufev->be_ops->destruct)
|
||||
bufev->be_ops->destruct(bufev);
|
||||
@ -536,6 +539,15 @@ _bufferevent_decref_and_unlock(struct bufferevent *bufev)
|
||||
|
||||
/* Free the actual allocated memory. */
|
||||
mm_free(bufev - bufev->be_ops->mem_offset);
|
||||
|
||||
/* release the reference to underlying now that we no longer need
|
||||
* the reference to it. This is mainly in case our lock is shared
|
||||
* with underlying.
|
||||
* XXX Should we/can we just refcount evbuffer/bufferevent locks?
|
||||
* It would probably save us some headaches.
|
||||
*/
|
||||
if (underlying)
|
||||
bufferevent_decref(underlying);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -200,6 +200,7 @@ bufferevent_filter_new(struct bufferevent *underlying,
|
||||
bufferevent_filtered_outbuf_cb, bufev_f);
|
||||
|
||||
_bufferevent_init_generic_timeout_cbs(downcast(bufev_f));
|
||||
bufferevent_incref(underlying);
|
||||
|
||||
return downcast(bufev_f);
|
||||
}
|
||||
|
@ -1101,8 +1101,10 @@ bufferevent_openssl_new_impl(struct event_base *base,
|
||||
if (options & BEV_OPT_THREADSAFE)
|
||||
bufferevent_enable_locking(&bev_ssl->bev.bev, NULL);
|
||||
|
||||
if (underlying)
|
||||
if (underlying) {
|
||||
_bufferevent_init_generic_timeout_cbs(&bev_ssl->bev.bev);
|
||||
bufferevent_incref(underlying);
|
||||
}
|
||||
|
||||
bev_ssl->state = state;
|
||||
bev_ssl->last_write = -1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user