summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Kozlov <xeb@mail.ru>2013-11-07 23:09:18 +0400
committerDmitry Kozlov <xeb@mail.ru>2013-11-07 23:09:18 +0400
commit878dee97686f6d981c891be9df562afe0b0dcc49 (patch)
treef964df8988bbc04e8bdb77736c7e0ba34a04940e
parent03b2f3ab32112b85c8aacc7057f3e8da0f09c82d (diff)
downloadaccel-ppp-878dee97686f6d981c891be9df562afe0b0dcc49.tar.gz
accel-ppp-878dee97686f6d981c891be9df562afe0b0dcc49.zip
shaper: fixed many race conditions
-rw-r--r--accel-pppd/shaper/shaper.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/accel-pppd/shaper/shaper.c b/accel-pppd/shaper/shaper.c
index d1742b4..d6482cf 100644
--- a/accel-pppd/shaper/shaper.c
+++ b/accel-pppd/shaper/shaper.c
@@ -439,7 +439,7 @@ static void ev_ppp_finishing(struct ppp_t *ppp)
if (pd->down_speed || pd->up_speed)
remove_limiter(ppp);
- if (--pd->refs == 0) {
+ if (__sync_sub_and_fetch(&pd->refs, 1) == 0) {
clear_tr_pd(pd);
_free(pd);
} else
@@ -455,6 +455,9 @@ static void shaper_change_help(char * const *f, int f_cnt, void *cli)
static void shaper_change(struct shaper_pd_t *pd)
{
+ if (!pd->ppp || pd->ppp->terminating)
+ goto out;
+
if (pd->down_speed || pd->up_speed)
remove_limiter(pd->ppp);
@@ -470,6 +473,12 @@ static void shaper_change(struct shaper_pd_t *pd)
pd->down_speed = 0;
pd->up_speed = 0;
}
+
+out:
+ if (__sync_sub_and_fetch(&pd->refs, 1) == 0) {
+ clear_tr_pd(pd);
+ _free(pd);
+ }
}
static int shaper_change_exec(const char *cmd, char * const *f, int f_cnt, void *cli)
@@ -519,6 +528,7 @@ static int shaper_change_exec(const char *cmd, char * const *f, int f_cnt, void
pd->cur_tr->up_speed = up_speed;
pd->cur_tr->up_burst = up_burst;
}
+ __sync_add_and_fetch(&pd->refs, 1);
triton_context_call(pd->ppp->ctrl->ctx, (triton_event_func)shaper_change, pd);
if (!all) {
found = 1;
@@ -542,6 +552,9 @@ static void shaper_restore_help(char * const *f, int f_cnt, void *cli)
static void shaper_restore(struct shaper_pd_t *pd)
{
+ if (!pd->ppp || pd->ppp->terminating)
+ goto out;
+
remove_limiter(pd->ppp);
if (pd->cur_tr) {
@@ -552,6 +565,12 @@ static void shaper_restore(struct shaper_pd_t *pd)
pd->down_speed = 0;
pd->up_speed = 0;
}
+
+out:
+ if (__sync_sub_and_fetch(&pd->refs, 1) == 0) {
+ clear_tr_pd(pd);
+ _free(pd);
+ }
}
static int shaper_restore_exec(const char *cmd, char * const *f, int f_cnt, void *cli)
@@ -578,6 +597,7 @@ static int shaper_restore_exec(const char *cmd, char * const *f, int f_cnt, void
if (all || !strcmp(f[2], pd->ppp->ifname)) {
pd->temp_down_speed = 0;
pd->temp_up_speed = 0;
+ __sync_add_and_fetch(&pd->refs, 1);
triton_context_call(pd->ppp->ctrl->ctx, (triton_event_func)shaper_restore, pd);
if (!all) {
found = 1;
@@ -655,7 +675,7 @@ static void update_shaper_tr(struct shaper_pd_t *pd)
log_ppp_info2("shaper: removed shaper\n");
out:
- if (--pd->refs == 0) {
+ if (__sync_sub_and_fetch(&pd->refs, 1) == 0) {
clear_tr_pd(pd);
_free(pd);
}
@@ -672,7 +692,7 @@ static void time_range_begin_timer(struct triton_timer_t *t)
pthread_rwlock_rdlock(&shaper_lock);
list_for_each_entry(pd, &shaper_list, entry) {
- pd->refs++;
+ __sync_add_and_fetch(&pd->refs, 1);
triton_context_call(pd->ppp->ctrl->ctx, (triton_event_func)update_shaper_tr, pd);
}
pthread_rwlock_unlock(&shaper_lock);
@@ -688,7 +708,7 @@ static void time_range_end_timer(struct triton_timer_t *t)
pthread_rwlock_rdlock(&shaper_lock);
list_for_each_entry(pd, &shaper_list, entry) {
- pd->refs++;
+ __sync_add_and_fetch(&pd->refs, 1);
triton_context_call(pd->ppp->ctrl->ctx, (triton_event_func)update_shaper_tr, pd);
}
pthread_rwlock_unlock(&shaper_lock);