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.
if (bufev_private->rate_limiting) {
if (bufev_private->rate_limiting->group)
- bufferevent_remove_from_rate_limit_group(bufev);
+ bufferevent_remove_from_rate_limit_group_internal(bufev,0);
if (event_initialized(&bufev_private->rate_limiting->refill_bucket_event))
event_del(&bufev_private->rate_limiting->refill_bucket_event);
event_debug_unassign(&bufev_private->rate_limiting->refill_bucket_event);
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);
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;
}
ev_uint32_t current_tick,
int reinitialize);
+int bufferevent_remove_from_rate_limit_group_internal(struct bufferevent *bev,
+ int unsuspend);
+
/** Decrease the read limit of 'b' by 'n' bytes */
#define ev_token_bucket_decrement_read(b,n) \
do { \
sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */
sin.sin_port = 0; /* unspecified port */
+ if (0)
+ event_enable_debug_mode();
+
base = event_base_new();
+
listener = evconnlistener_new_bind(base, echo_listenercb, base,
LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1,
(struct sockaddr *)&sin, sizeof(sin));