diff options
author | Dmitry Kozlov <xeb@mail.ru> | 2013-11-07 23:09:18 +0400 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2013-11-07 23:09:18 +0400 |
commit | 878dee97686f6d981c891be9df562afe0b0dcc49 (patch) | |
tree | f964df8988bbc04e8bdb77736c7e0ba34a04940e | |
parent | 03b2f3ab32112b85c8aacc7057f3e8da0f09c82d (diff) | |
download | accel-ppp-878dee97686f6d981c891be9df562afe0b0dcc49.tar.gz accel-ppp-878dee97686f6d981c891be9df562afe0b0dcc49.zip |
shaper: fixed many race conditions
-rw-r--r-- | accel-pppd/shaper/shaper.c | 28 |
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); |