mirror of
https://github.com/cuberite/libevent.git
synced 2025-08-04 01:36:23 -04:00
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.
This commit is contained in:
parent
ff481a8e43
commit
0bffe43a15
@ -608,7 +608,7 @@ _bufferevent_decref_and_unlock(struct bufferevent *bufev)
|
|||||||
|
|
||||||
if (bufev_private->rate_limiting) {
|
if (bufev_private->rate_limiting) {
|
||||||
if (bufev_private->rate_limiting->group)
|
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))
|
if (event_initialized(&bufev_private->rate_limiting->refill_bucket_event))
|
||||||
event_del(&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);
|
event_debug_unassign(&bufev_private->rate_limiting->refill_bucket_event);
|
||||||
|
@ -715,6 +715,13 @@ bufferevent_add_to_rate_limit_group(struct bufferevent *bev,
|
|||||||
|
|
||||||
int
|
int
|
||||||
bufferevent_remove_from_rate_limit_group(struct bufferevent *bev)
|
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 =
|
struct bufferevent_private *bevp =
|
||||||
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
|
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
|
||||||
@ -728,8 +735,10 @@ bufferevent_remove_from_rate_limit_group(struct bufferevent *bev)
|
|||||||
TAILQ_REMOVE(&g->members, bevp, rate_limiting->next_in_group);
|
TAILQ_REMOVE(&g->members, bevp, rate_limiting->next_in_group);
|
||||||
UNLOCK_GROUP(g);
|
UNLOCK_GROUP(g);
|
||||||
}
|
}
|
||||||
|
if (unsuspend) {
|
||||||
bufferevent_unsuspend_read(bev, BEV_SUSPEND_BW_GROUP);
|
bufferevent_unsuspend_read(bev, BEV_SUSPEND_BW_GROUP);
|
||||||
bufferevent_unsuspend_write(bev, BEV_SUSPEND_BW_GROUP);
|
bufferevent_unsuspend_write(bev, BEV_SUSPEND_BW_GROUP);
|
||||||
|
}
|
||||||
BEV_UNLOCK(bev);
|
BEV_UNLOCK(bev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -84,6 +84,9 @@ int ev_token_bucket_init(struct ev_token_bucket *bucket,
|
|||||||
ev_uint32_t current_tick,
|
ev_uint32_t current_tick,
|
||||||
int reinitialize);
|
int reinitialize);
|
||||||
|
|
||||||
|
int bufferevent_remove_from_rate_limit_group_internal(struct bufferevent *bev,
|
||||||
|
int unsuspend);
|
||||||
|
|
||||||
/** Decrease the read limit of 'b' by 'n' bytes */
|
/** Decrease the read limit of 'b' by 'n' bytes */
|
||||||
#define ev_token_bucket_decrement_read(b,n) \
|
#define ev_token_bucket_decrement_read(b,n) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -187,7 +187,11 @@ test_ratelimiting(void)
|
|||||||
sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */
|
sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */
|
||||||
sin.sin_port = 0; /* unspecified port */
|
sin.sin_port = 0; /* unspecified port */
|
||||||
|
|
||||||
|
if (0)
|
||||||
|
event_enable_debug_mode();
|
||||||
|
|
||||||
base = event_base_new();
|
base = event_base_new();
|
||||||
|
|
||||||
listener = evconnlistener_new_bind(base, echo_listenercb, base,
|
listener = evconnlistener_new_bind(base, echo_listenercb, base,
|
||||||
LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1,
|
LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1,
|
||||||
(struct sockaddr *)&sin, sizeof(sin));
|
(struct sockaddr *)&sin, sizeof(sin));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user