From db218bbe19b66a382df5f665981b7b16f1901bc9 Mon Sep 17 00:00:00 2001
From: dimitri staessens <dimitri.staessens@ugent.be>
Date: Thu, 17 Aug 2017 16:35:36 +0200
Subject: irmd: Handle IPCP creation fails gracefully

---
 src/irmd/ipcp.c | 53 ++++++++++++++++++++++++-----------------------------
 src/irmd/main.c | 34 ++++++++++++++++++++++++++++------
 2 files changed, 52 insertions(+), 35 deletions(-)

diff --git a/src/irmd/ipcp.c b/src/irmd/ipcp.c
index ade09625..f3f97811 100644
--- a/src/irmd/ipcp.c
+++ b/src/irmd/ipcp.c
@@ -130,13 +130,34 @@ pid_t ipcp_create(const char *   name,
                   enum ipcp_type ipcp_type)
 {
         pid_t  api       = -1;
-        size_t len       = 0;
         char * ipcp_dir  = "/sbin/";
-        char * full_name = NULL;
         char * exec_name = NULL;
         char   irmd_api[10];
+        char   full_name[256];
         char * argv[5];
 
+        switch(ipcp_type) {
+        case IPCP_NORMAL:
+                exec_name = IPCP_NORMAL_EXEC;
+                break;
+        case IPCP_SHIM_UDP:
+                exec_name = IPCP_SHIM_UDP_EXEC;
+                break;
+        case IPCP_SHIM_ETH_LLC:
+                exec_name = IPCP_SHIM_ETH_LLC_EXEC;
+                break;
+        case IPCP_LOCAL:
+                exec_name = IPCP_LOCAL_EXEC;
+                break;
+        default:
+                return -1;
+        }
+
+        if (strlen(exec_name) == 0) {
+                log_err("IPCP type not installed.");
+                return -1;
+        }
+
         sprintf(irmd_api, "%u", getpid());
 
         api = fork();
@@ -148,33 +169,9 @@ pid_t ipcp_create(const char *   name,
         if (api != 0)
                 return api;
 
-        if (ipcp_type == IPCP_NORMAL)
-                exec_name = IPCP_NORMAL_EXEC;
-        else if (ipcp_type == IPCP_SHIM_UDP)
-                exec_name = IPCP_SHIM_UDP_EXEC;
-        else if (ipcp_type == IPCP_SHIM_ETH_LLC)
-                exec_name = IPCP_SHIM_ETH_LLC_EXEC;
-        else if (ipcp_type == IPCP_LOCAL)
-                exec_name = IPCP_LOCAL_EXEC;
-        else
-                exit(EXIT_FAILURE);
-
-        len += strlen(INSTALL_PREFIX);
-        len += strlen(ipcp_dir);
-        len += strlen(exec_name);
-        len += 1;
-
-        full_name = malloc(len + 1);
-        if (full_name == NULL) {
-                log_err("Failed to malloc");
-                exit(EXIT_FAILURE);
-        }
-
         strcpy(full_name, INSTALL_PREFIX);
         strcat(full_name, ipcp_dir);
         strcat(full_name, exec_name);
-        full_name[len] = '\0';
-
 
         /* log_file to be placed at the end */
         argv[0] = full_name;
@@ -190,9 +187,7 @@ pid_t ipcp_create(const char *   name,
         execv(argv[0], &argv[0]);
 
         log_dbg("%s", strerror(errno));
-        log_err("Failed to load IPCP daemon");
-        log_err("Make sure to run the installed version");
-        free(full_name);
+        log_err("Failed to load IPCP daemon.");
         exit(EXIT_FAILURE);
 }
 
diff --git a/src/irmd/main.c b/src/irmd/main.c
index 61ce6a49..0c157fd4 100644
--- a/src/irmd/main.c
+++ b/src/irmd/main.c
@@ -275,6 +275,11 @@ static pid_t create_ipcp(char *         name,
         struct ipcp_entry * tmp   = NULL;
         struct list_head *  p     = NULL;
         struct ipcp_entry * entry = NULL;
+        int                 ret   = 0;
+        pthread_condattr_t  cattr;
+        struct timespec     dl;
+        struct timespec     to = {SOCKET_TIMEOUT / 1000,
+                                  (SOCKET_TIMEOUT % 1000) * MILLION};
 
         api = malloc(sizeof(*api));
         if (api == NULL)
@@ -311,13 +316,20 @@ static pid_t create_ipcp(char *         name,
                 pthread_rwlock_unlock(&irmd.reg_lock);
                 return -1;
         }
+        pthread_condattr_init(&cattr);
+#ifndef __APPLE__
+        pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK);
+#endif
+
+        pthread_cond_init(&tmp->init_cond, &cattr);
+
+        pthread_condattr_destroy(&cattr);
 
-        pthread_cond_init(&tmp->init_cond, NULL);
         pthread_mutex_init(&tmp->init_lock, NULL);
 
-        tmp->dif_name = NULL;
-        tmp->type = ipcp_type;
-        tmp->init = false;
+        tmp->dif_name      = NULL;
+        tmp->type          = ipcp_type;
+        tmp->init          = false;
         tmp->dir_hash_algo = -1;
 
         list_for_each(p, &irmd.ipcps) {
@@ -334,11 +346,21 @@ static pid_t create_ipcp(char *         name,
 
         pthread_mutex_lock(&tmp->init_lock);
 
-        while (tmp->init == false)
-                pthread_cond_wait(&tmp->init_cond, &tmp->init_lock);
+        clock_gettime(PTHREAD_COND_CLOCK, &dl);
+        ts_add(&dl, &to, &dl);
 
+        while (tmp->init == false && ret != -ETIMEDOUT)
+                ret = -pthread_cond_timedwait(&tmp->init_cond,
+                                              &tmp->init_lock,
+                                              &dl);
         pthread_mutex_unlock(&tmp->init_lock);
 
+        if (ret == -ETIMEDOUT) {
+                log_err("Process %d failed to respond.", api->pid);
+                kill(api->pid, SIGKILL);
+                return -1;
+        }
+
         log_info("Created IPCP %d.", api->pid);
 
         return api->pid;
-- 
cgit v1.2.3