diff options
author | Nick Mathewson <nickm@torproject.org> | 2010-03-12 23:00:49 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2010-03-13 00:28:50 -0500 |
commit | f1bc125eb453af61cbb750652103532b77c271b0 (patch) | |
tree | 76f69d8977e9b40fbdd9e027d7fdbb4afc192105 /bufferevent.c | |
parent | 6c83e6c9725ad61f8d28955ee7a5d1f3162d74d0 (diff) | |
download | libevent-f1bc125eb453af61cbb750652103532b77c271b0.tar.gz |
Improve robustness for refcounting
Document that we do intend to double-decref underlying bufferevents under
some circumstances. Check to make sure that we don't decref past 0.
Diffstat (limited to 'bufferevent.c')
-rw-r--r-- | bufferevent.c | 40 |
1 files changed, 33 insertions, 7 deletions
diff --git a/bufferevent.c b/bufferevent.c index 7fef8bb6..958fff90 100644 --- a/bufferevent.c +++ b/bufferevent.c @@ -504,16 +504,36 @@ _bufferevent_incref_and_lock(struct bufferevent *bufev) ++bufev_private->refcnt; } -void +#if 0 +static void +_bufferevent_transfer_lock_ownership(struct bufferevent *donor, + struct bufferevent *recipient) +{ + struct bufferevent_private *d = BEV_UPCAST(donor); + struct bufferevent_private *r = BEV_UPCAST(recipient); + if (d->lock != r->lock) + return; + if (r->own_lock) + return; + if (d->own_lock) { + d->own_lock = 0; + r->own_lock = 1; + } +} +#endif + +int _bufferevent_decref_and_unlock(struct bufferevent *bufev) { struct bufferevent_private *bufev_private = EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); struct bufferevent *underlying; + EVUTIL_ASSERT(bufev_private->refcnt > 0); + if (--bufev_private->refcnt) { BEV_UNLOCK(bufev); - return; + return 0; } underlying = bufferevent_get_underlying(bufev); @@ -550,21 +570,27 @@ _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. + /* Release the reference to underlying now that we no longer need the + * reference to it. We wait this long mainly in case our lock is + * shared with underlying. + * + * The 'destruct' function will also drop a reference to underlying + * if BEV_OPT_CLOSE_ON_FREE is set. + * * XXX Should we/can we just refcount evbuffer/bufferevent locks? * It would probably save us some headaches. */ if (underlying) bufferevent_decref(underlying); + + return 1; } -void +int bufferevent_decref(struct bufferevent *bufev) { BEV_LOCK(bufev); - _bufferevent_decref_and_unlock(bufev); + return _bufferevent_decref_and_unlock(bufev); } void |