diff options
author | Kozlov Dmitry <xeb@mail.ru> | 2013-08-27 21:57:20 +0400 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2013-08-27 22:59:27 +0400 |
commit | 4ba1e612c56df1a103bd2d0de67f52ceda04765e (patch) | |
tree | fd08f90311aef8f6d50032bf48768f16940b3122 | |
parent | d7c79acddfdc28c333eb5029f1790477f34601cd (diff) | |
download | accel-ppp-4ba1e612c56df1a103bd2d0de67f52ceda04765e.tar.gz accel-ppp-4ba1e612c56df1a103bd2d0de67f52ceda04765e.zip |
shaper: fixed possible race during changing time range
-rw-r--r-- | accel-pppd/shaper/shaper.c | 42 |
1 files changed, 27 insertions, 15 deletions
diff --git a/accel-pppd/shaper/shaper.c b/accel-pppd/shaper/shaper.c index 09f03f39..b89ad36a 100644 --- a/accel-pppd/shaper/shaper.c +++ b/accel-pppd/shaper/shaper.c @@ -57,8 +57,7 @@ static pthread_rwlock_t shaper_lock = PTHREAD_RWLOCK_INITIALIZER; static LIST_HEAD(shaper_list); struct time_range_pd_t; -struct shaper_pd_t -{ +struct shaper_pd_t { struct list_head entry; struct ap_session *ses; struct ap_private pd; @@ -68,10 +67,10 @@ struct shaper_pd_t int up_speed; struct list_head tr_list; struct time_range_pd_t *cur_tr; + int refs; }; -struct time_range_pd_t -{ +struct time_range_pd_t { struct list_head entry; int id; int down_speed; @@ -80,8 +79,7 @@ struct time_range_pd_t int up_burst; }; -struct time_range_t -{ +struct time_range_t { struct list_head entry; int id; struct triton_timer_t begin; @@ -123,6 +121,7 @@ static struct shaper_pd_t *find_pd(struct ap_session *ses, int create) list_add_tail(&spd->pd.entry, &ses->pd_list); spd->pd.key = &pd_key; INIT_LIST_HEAD(&spd->tr_list); + spd->refs = 1; pthread_rwlock_wrlock(&shaper_lock); list_add_tail(&spd->entry, &shaper_list); @@ -423,16 +422,20 @@ static void ev_ppp_finishing(struct ap_session *ses) struct shaper_pd_t *pd = find_pd(ses, 0); if (pd) { - clear_tr_pd(pd); pthread_rwlock_wrlock(&shaper_lock); list_del(&pd->entry); pthread_rwlock_unlock(&shaper_lock); + list_del(&pd->pd.entry); if (pd->down_speed || pd->up_speed) remove_limiter(ses); - _free(pd); + if (--pd->refs == 0) { + clear_tr_pd(pd); + _free(pd); + } else + pd->ses = NULL; } } @@ -613,8 +616,8 @@ static void update_shaper_tr(struct shaper_pd_t *pd) { struct time_range_pd_t *tr; - if (pd->ses->terminating) - return; + if (!pd->ses || pd->ses->terminating) + goto out; list_for_each_entry(tr, &pd->tr_list, entry) { if (tr->id != time_range_id) @@ -624,11 +627,11 @@ static void update_shaper_tr(struct shaper_pd_t *pd) } if (pd->temp_down_speed || pd->temp_up_speed) - return; + goto out; if (pd->down_speed || pd->up_speed) { if (pd->cur_tr && pd->down_speed == pd->cur_tr->down_speed && pd->up_speed == pd->cur_tr->up_speed) - return; + goto out; remove_limiter(pd->ses); } @@ -639,9 +642,16 @@ static void update_shaper_tr(struct shaper_pd_t *pd) if (conf_verbose) log_ppp_info2("shaper: changed shaper %i/%i (Kbit)\n", pd->cur_tr->down_speed, pd->cur_tr->up_speed); } - } else + } else { if (conf_verbose) - log_ppp_info2("shaper: removed shaper\n"); + log_ppp_info2("shaper: removed shaper\n"); + } + +out: + if (--pd->refs == 0) { + clear_tr_pd(pd); + _free(pd); + } } static void time_range_begin_timer(struct triton_timer_t *t) @@ -654,8 +664,10 @@ static void time_range_begin_timer(struct triton_timer_t *t) log_debug("shaper: time_range_begin_timer: id=%i\n", time_range_id); pthread_rwlock_rdlock(&shaper_lock); - list_for_each_entry(pd, &shaper_list, entry) + list_for_each_entry(pd, &shaper_list, entry) { + pd->refs++; triton_context_call(pd->ses->ctrl->ctx, (triton_event_func)update_shaper_tr, pd); + } pthread_rwlock_unlock(&shaper_lock); } |