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:18:08 +0400 |
commit | 5ee3cf66bbe9b7f6197aab39417269ce95c3c95c (patch) | |
tree | 3453654786c0cf391d64a04d61f40349e08aba52 /accel-pppd/shaper | |
parent | e6fa57219f8fe21c164a3e851d71d696e3e1386c (diff) | |
download | accel-ppp-5ee3cf66bbe9b7f6197aab39417269ce95c3c95c.tar.gz accel-ppp-5ee3cf66bbe9b7f6197aab39417269ce95c3c95c.zip |
shaper: fixed many race conditions
Signed-off-by: Dmitry Kozlov <xeb@mail.ru>
Diffstat (limited to 'accel-pppd/shaper')
-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 369a375b..7219d727 100644 --- a/accel-pppd/shaper/shaper.c +++ b/accel-pppd/shaper/shaper.c @@ -431,7 +431,7 @@ static void ev_ppp_finishing(struct ap_session *ses) if (pd->down_speed || pd->up_speed) remove_limiter(ses); - if (--pd->refs == 0) { + if (__sync_sub_and_fetch(&pd->refs, 1) == 0) { clear_tr_pd(pd); _free(pd); } else @@ -447,6 +447,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->ses || pd->ses->terminating) + goto out; + if (pd->down_speed || pd->up_speed) remove_limiter(pd->ses); @@ -462,6 +465,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) @@ -511,6 +520,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->ses->ctrl->ctx, (triton_event_func)shaper_change, pd); if (!all) { found = 1; @@ -534,6 +544,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->ses || pd->ses->terminating) + goto out; + remove_limiter(pd->ses); if (pd->cur_tr) { @@ -544,6 +557,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) @@ -570,6 +589,7 @@ static int shaper_restore_exec(const char *cmd, char * const *f, int f_cnt, void if (all || !strcmp(f[2], pd->ses->ifname)) { pd->temp_down_speed = 0; pd->temp_up_speed = 0; + __sync_add_and_fetch(&pd->refs, 1); triton_context_call(pd->ses->ctrl->ctx, (triton_event_func)shaper_restore, pd); if (!all) { found = 1; @@ -648,7 +668,7 @@ static void update_shaper_tr(struct shaper_pd_t *pd) } out: - if (--pd->refs == 0) { + if (__sync_sub_and_fetch(&pd->refs, 1) == 0) { clear_tr_pd(pd); _free(pd); } @@ -665,7 +685,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->ses->ctrl->ctx, (triton_event_func)update_shaper_tr, pd); } pthread_rwlock_unlock(&shaper_lock); @@ -681,7 +701,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->ses->ctrl->ctx, (triton_event_func)update_shaper_tr, pd); } pthread_rwlock_unlock(&shaper_lock); |