diff options
author | Dmitry Kozlov <xeb@mail.ru> | 2014-10-22 19:23:02 +0400 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2014-10-22 19:23:02 +0400 |
commit | c73bda7c792a850dc24dc22cf6065eaaad717b69 (patch) | |
tree | 760a5bde1d244bd5291e37fca4b7995baecf886d | |
parent | a3f7e7d1e26bcf1ddb4d86d06f8a3a976374eade (diff) | |
download | accel-ppp-c73bda7c792a850dc24dc22cf6065eaaad717b69.tar.gz accel-ppp-c73bda7c792a850dc24dc22cf6065eaaad717b69.zip |
ppp: implemented delayed unit close via unit cache
Due to kernel slowly destroys interfaces closing unit file descriptor blocks working threads which causes overall stuck.
Thus (if unit-cache option is not zero) do not close unit file descriptor immediatly, but put it into unit cache.
Additional helper thread was introduced which closes descriptors from unit cache which overruns configured unit cache size.
-rw-r--r-- | accel-pppd/accel-ppp.conf | 2 | ||||
-rw-r--r-- | accel-pppd/ppp/ppp.c | 61 |
2 files changed, 53 insertions, 10 deletions
diff --git a/accel-pppd/accel-ppp.conf b/accel-pppd/accel-ppp.conf index 93dca1fa..ef8c822c 100644 --- a/accel-pppd/accel-ppp.conf +++ b/accel-pppd/accel-ppp.conf @@ -56,7 +56,7 @@ ipv6-accept-peer-intf-id=1 lcp-echo-interval=20 #lcp-echo-failure=3 lcp-echo-timeout=120 -#unit-cache=1000 +unit-cache=1 [auth] #any-login=0 diff --git a/accel-pppd/ppp/ppp.c b/accel-pppd/ppp/ppp.c index fd572590..6329b89c 100644 --- a/accel-pppd/ppp/ppp.c +++ b/accel-pppd/ppp/ppp.c @@ -48,7 +48,9 @@ struct pppunit_cache int unit_idx; }; +static pthread_t uc_thr; static pthread_mutex_t uc_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t uc_cond = PTHREAD_COND_INITIALIZER; static LIST_HEAD(uc_list); static int uc_size; static mempool_t uc_pool; @@ -76,6 +78,9 @@ int __export establish_ppp(struct ppp_t *ppp) { struct pppunit_cache *uc = NULL; + if (ap_shutdown) + return -1; + /* Open an instance of /dev/ppp and connect the channel to it */ if (ioctl(ppp->fd, PPPIOCGCHAN, &ppp->chan_idx) == -1) { log_ppp_error("ioctl(PPPIOCGCHAN): %s\n", strerror(errno)); @@ -165,7 +170,8 @@ int __export establish_ppp(struct ppp_t *ppp) log_ppp_debug("ppp established\n"); - ap_session_starting(&ppp->ses); + if (ap_session_starting(&ppp->ses)) + goto exit_close_unit; start_first_layer(ppp); @@ -185,28 +191,29 @@ exit_close_chan: static void destablish_ppp(struct ppp_t *ppp) { struct pppunit_cache *uc; - int close_unit = uc_size >= conf_unit_cache; triton_event_fire(EV_SES_PRE_FINISHED, &ppp->ses); triton_md_unregister_handler(&ppp->chan_hnd, 1); - triton_md_unregister_handler(&ppp->unit_hnd, close_unit); - if (!close_unit) { + if (conf_unit_cache) { + triton_md_unregister_handler(&ppp->unit_hnd, 0); uc = mempool_alloc(uc_pool); uc->fd = ppp->unit_fd; uc->unit_idx = ppp->ses.unit_idx; pthread_mutex_lock(&uc_lock); list_add_tail(&uc->entry, &uc_list); - ++uc_size; - pthread_mutex_unlock(&uc_lock); - - ppp->chan_fd = -1; - } + if (++uc_size > conf_unit_cache) + pthread_cond_signal(&uc_cond); + pthread_mutex_unlock(&uc_lock); + } else + triton_md_unregister_handler(&ppp->unit_hnd, 1); close(ppp->fd); ppp->fd = -1; + ppp->chan_fd = -1; + ppp->unit_fd = -1; _free_layers(ppp); @@ -217,6 +224,40 @@ static void destablish_ppp(struct ppp_t *ppp) ap_session_finished(&ppp->ses); } +static void *uc_thread(void *unused) +{ + struct pppunit_cache *uc; + int fd; + sigset_t set; + + sigfillset(&set); + sigdelset(&set, SIGKILL); + sigdelset(&set, SIGSTOP); + + pthread_sigmask(SIG_BLOCK, &set, NULL); + + while (1) { + pthread_mutex_lock(&uc_lock); + if (uc_size > conf_unit_cache) { + uc = list_entry(uc_list.next, typeof(*uc), entry); + list_del(&uc->entry); + --uc_size; + pthread_mutex_unlock(&uc_lock); + + fd = uc->fd; + + mempool_free(uc); + + close(fd); + continue; + } + pthread_cond_wait(&uc_cond, &uc_lock); + pthread_mutex_unlock(&uc_lock); + } + + return NULL; +} + /*void print_buf(uint8_t *buf, int size) { int i; @@ -610,6 +651,8 @@ static void init(void) load_config(); triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); + + pthread_create(&uc_thr, NULL, uc_thread, NULL); } DEFINE_INIT(2, init); |