summaryrefslogtreecommitdiff
path: root/bufferevent.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2010-03-12 23:00:49 -0500
committerNick Mathewson <nickm@torproject.org>2010-03-13 00:28:50 -0500
commitf1bc125eb453af61cbb750652103532b77c271b0 (patch)
tree76f69d8977e9b40fbdd9e027d7fdbb4afc192105 /bufferevent.c
parent6c83e6c9725ad61f8d28955ee7a5d1f3162d74d0 (diff)
downloadlibevent-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.c40
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