summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Kozlov <xeb@mail.ru>2014-10-22 19:23:02 +0400
committerDmitry Kozlov <xeb@mail.ru>2014-10-22 19:23:02 +0400
commitc73bda7c792a850dc24dc22cf6065eaaad717b69 (patch)
tree760a5bde1d244bd5291e37fca4b7995baecf886d
parenta3f7e7d1e26bcf1ddb4d86d06f8a3a976374eade (diff)
downloadaccel-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.conf2
-rw-r--r--accel-pppd/ppp/ppp.c61
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);