From: Nick Mathewson Date: Mon, 22 Feb 2010 20:38:23 +0000 (-0500) Subject: Make bufferevent_free() clear all callbacks immediately. X-Git-Tag: release-2.0.4-alpha~15^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b2fbeb3f074258e4559aa879ef0cbe0ef415ed0f;p=libevent Make bufferevent_free() clear all callbacks immediately. This should end the family of bugs where we call bufferevent_free() while a pending callback is holding a reference on the bufferevent, and the callback tries to invoke the user callbacks before it releases its own final reference. This means that bufferevent_decref() is now a separate function from bufferevent_free(). --- diff --git a/buffer.c b/buffer.c index 7185bd1b..08b9cba9 100644 --- a/buffer.c +++ b/buffer.c @@ -413,7 +413,7 @@ evbuffer_deferred_callback(struct deferred_cb *cb, void *arg) evbuffer_run_callbacks(buffer, 1); _evbuffer_decref_and_unlock(buffer); if (parent) - bufferevent_free(parent); + bufferevent_decref(parent); } static void diff --git a/bufferevent-internal.h b/bufferevent-internal.h index ad1f844e..9cc9fbbc 100644 --- a/bufferevent-internal.h +++ b/bufferevent-internal.h @@ -274,11 +274,11 @@ void bufferevent_incref(struct bufferevent *bufev); /** Internal: Lock bufev and increase its reference count. * unlocking it otherwise. */ void _bufferevent_incref_and_lock(struct bufferevent *bufev); +/** Internal: Increment the reference count on bufev. */ +void bufferevent_decref(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. */ diff --git a/bufferevent.c b/bufferevent.c index 4a7b46a4..3864cece 100644 --- a/bufferevent.c +++ b/bufferevent.c @@ -560,10 +560,18 @@ _bufferevent_decref_and_unlock(struct bufferevent *bufev) bufferevent_decref(underlying); } +void +bufferevent_decref(struct bufferevent *bufev) +{ + BEV_LOCK(bufev); + _bufferevent_decref_and_unlock(bufev); +} + void bufferevent_free(struct bufferevent *bufev) { BEV_LOCK(bufev); + bufferevent_setcb(bufev, NULL, NULL, NULL, NULL); _bufferevent_decref_and_unlock(bufev); }