summaryrefslogtreecommitdiff
path: root/bufferevent_ratelim.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2010-08-09 12:08:40 -0400
committerNick Mathewson <nickm@torproject.org>2010-08-09 12:08:40 -0400
commit0bffe43a15fbd43bc7826acb88a3bada528c8adf (patch)
treef3f4ce3467227d47693f9b334ef7175790424e39 /bufferevent_ratelim.c
parentff481a8e43999c4ba1556bc472b5e69fce7ea353 (diff)
downloadlibevent-0bffe43a15fbd43bc7826acb88a3bada528c8adf.tar.gz
Fix a nasty dangling-event bug when using rate-limiting groups
When we freed a bufferevent that was in a rate-limiting group and blocked on IO, the process of freeing it caused it to get removed from the group. But removing the bufferevent from the group made its limits get removed, which could make it get un-suspended and in turn cause its events to get re-added. Since we would then immediately _free_ the events, this would result in dangling pointers. Fixes bug 3041007.
Diffstat (limited to 'bufferevent_ratelim.c')
-rw-r--r--bufferevent_ratelim.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/bufferevent_ratelim.c b/bufferevent_ratelim.c
index cb8a3bf5..7ac579ac 100644
--- a/bufferevent_ratelim.c
+++ b/bufferevent_ratelim.c
@@ -716,6 +716,13 @@ bufferevent_add_to_rate_limit_group(struct bufferevent *bev,
int
bufferevent_remove_from_rate_limit_group(struct bufferevent *bev)
{
+ return bufferevent_remove_from_rate_limit_group_internal(bev, 1);
+}
+
+int
+bufferevent_remove_from_rate_limit_group_internal(struct bufferevent *bev,
+ int unsuspend)
+{
struct bufferevent_private *bevp =
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
BEV_LOCK(bev);
@@ -728,8 +735,10 @@ bufferevent_remove_from_rate_limit_group(struct bufferevent *bev)
TAILQ_REMOVE(&g->members, bevp, rate_limiting->next_in_group);
UNLOCK_GROUP(g);
}
- bufferevent_unsuspend_read(bev, BEV_SUSPEND_BW_GROUP);
- bufferevent_unsuspend_write(bev, BEV_SUSPEND_BW_GROUP);
+ if (unsuspend) {
+ bufferevent_unsuspend_read(bev, BEV_SUSPEND_BW_GROUP);
+ bufferevent_unsuspend_write(bev, BEV_SUSPEND_BW_GROUP);
+ }
BEV_UNLOCK(bev);
return 0;
}