summaryrefslogtreecommitdiff
path: root/src/irmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/irmd')
-rw-r--r--src/irmd/main.c63
1 files changed, 61 insertions, 2 deletions
diff --git a/src/irmd/main.c b/src/irmd/main.c
index c2058ed5..e36fb98e 100644
--- a/src/irmd/main.c
+++ b/src/irmd/main.c
@@ -63,6 +63,9 @@ struct ipcp_entry {
pid_t api;
enum ipcp_type type;
char * dif_name;
+ pthread_cond_t init_cond;
+ pthread_mutex_t init_lock;
+ bool init;
};
enum irm_state {
@@ -243,8 +246,11 @@ static pid_t create_ipcp(char * name,
return -1;
}
+ pthread_rwlock_wrlock(&irmd->reg_lock);
+
api->api = ipcp_create(ipcp_type);
if (api->api == -1) {
+ pthread_rwlock_unlock(&irmd->reg_lock);
pthread_rwlock_unlock(&irmd->state_lock);
LOG_ERR("Failed to create IPCP.");
return -1;
@@ -252,6 +258,7 @@ static pid_t create_ipcp(char * name,
tmp = ipcp_entry_create();
if (tmp == NULL) {
+ pthread_rwlock_unlock(&irmd->reg_lock);
pthread_rwlock_unlock(&irmd->state_lock);
return -1;
}
@@ -262,14 +269,17 @@ static pid_t create_ipcp(char * name,
tmp->name = strdup(name);
if (tmp->name == NULL) {
ipcp_entry_destroy(tmp);
+ pthread_rwlock_unlock(&irmd->reg_lock);
pthread_rwlock_unlock(&irmd->state_lock);
return -1;
}
+ pthread_cond_init(&tmp->init_cond, NULL);
+ pthread_mutex_init(&tmp->init_lock, NULL);
+
tmp->dif_name = NULL;
tmp->type = ipcp_type;
-
- pthread_rwlock_wrlock(&irmd->reg_lock);
+ tmp->init = false;
list_for_each(pos, &irmd->ipcps) {
struct ipcp_entry * e =
@@ -282,14 +292,46 @@ static pid_t create_ipcp(char * name,
list_add(&api->next, &irmd->spawned_apis);
+ pthread_mutex_lock(&tmp->init_lock);
+
pthread_rwlock_unlock(&irmd->reg_lock);
pthread_rwlock_unlock(&irmd->state_lock);
+ while (tmp->init == false)
+ pthread_cond_wait(&tmp->init_cond, &tmp->init_lock);
+
+ pthread_mutex_unlock(&tmp->init_lock);
+
LOG_INFO("Created IPCP %d.", api->api);
return api->api;
}
+static int create_ipcp_r(pid_t api)
+{
+ struct list_head * pos = NULL;
+
+ pthread_rwlock_rdlock(&irmd->state_lock);
+ pthread_rwlock_rdlock(&irmd->reg_lock);
+
+ list_for_each(pos, &irmd->ipcps) {
+ struct ipcp_entry * e =
+ list_entry(pos, struct ipcp_entry, next);
+
+ if (e->api == api) {
+ pthread_mutex_lock(&e->init_lock);
+ e->init = true;
+ pthread_cond_broadcast(&e->init_cond);
+ pthread_mutex_unlock(&e->init_lock);
+ }
+ }
+
+ pthread_rwlock_unlock(&irmd->reg_lock);
+ pthread_rwlock_unlock(&irmd->state_lock);
+
+ return 0;
+}
+
static void clear_spawned_api(pid_t api)
{
struct list_head * pos = NULL;
@@ -1320,6 +1362,8 @@ void * irm_flow_cleaner()
struct timespec now;
struct list_head * pos = NULL;
struct list_head * n = NULL;
+ struct list_head * h = NULL;
+ struct list_head * t = NULL;
struct timespec timeout = {IRMD_CLEANUP_TIMER / BILLION,
IRMD_CLEANUP_TIMER % BILLION};
@@ -1398,6 +1442,17 @@ void * irm_flow_cleaner()
LOG_INFO("Spawned process %d terminated "
"with exit status %d.",
api->api, status);
+
+ list_for_each_safe(h, t, &irmd->ipcps) {
+ struct ipcp_entry * e =
+ list_entry(h, struct ipcp_entry,
+ next);
+ if (e->api == api->api) {
+ list_del(&e->next);
+ ipcp_entry_destroy(e);
+ }
+ }
+
list_del(&api->next);
free(api);
}
@@ -1455,6 +1510,10 @@ void * mainloop()
ret_msg.result = create_ipcp(msg->dst_name,
msg->ipcp_type);
break;
+ case IRM_MSG_CODE__IPCP_CREATE_R:
+ ret_msg.has_result = true;
+ ret_msg.result = create_ipcp_r(msg->api);
+ break;
case IRM_MSG_CODE__IRM_DESTROY_IPCP:
ret_msg.has_result = true;
ret_msg.result = destroy_ipcp(msg->api);