summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKozlov Dmitry <xeb@mail.ru>2013-08-27 21:57:20 +0400
committerDmitry Kozlov <xeb@mail.ru>2013-08-27 22:59:27 +0400
commit4ba1e612c56df1a103bd2d0de67f52ceda04765e (patch)
treefd08f90311aef8f6d50032bf48768f16940b3122
parentd7c79acddfdc28c333eb5029f1790477f34601cd (diff)
downloadaccel-ppp-4ba1e612c56df1a103bd2d0de67f52ceda04765e.tar.gz
accel-ppp-4ba1e612c56df1a103bd2d0de67f52ceda04765e.zip
shaper: fixed possible race during changing time range
-rw-r--r--accel-pppd/shaper/shaper.c42
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);
}