diff options
| -rw-r--r-- | src/irmd/main.c | 145 | ||||
| -rw-r--r-- | src/irmd/registry.c | 12 | ||||
| -rw-r--r-- | src/irmd/registry.h | 12 | 
3 files changed, 121 insertions, 48 deletions
| diff --git a/src/irmd/main.c b/src/irmd/main.c index ddce2d61..ff129b71 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -51,7 +51,7 @@  #include <pthread.h>  #include <sys/stat.h>  #include <dirent.h> -#include <getopt.h> +#include <sys/wait.h>  #define IRMD_CLEANUP_TIMER ((IRMD_FLOW_TIMEOUT / 20) * MILLION) /* ns */ @@ -68,35 +68,42 @@ enum irm_state {          IRMD_SHUTDOWN  }; +struct spawned_api { +        struct list_head next; +        pid_t            api; +}; +  /* keeps track of port_id's between N and N - 1 */  struct port_map_entry {          struct list_head next; -        int port_id; +        int              port_id; -        pid_t n_api; -        pid_t n_1_api; +        pid_t            n_api; +        pid_t            n_1_api; -        pthread_cond_t  res_signal; -        pthread_mutex_t res_lock; +        pthread_cond_t   res_signal; +        pthread_mutex_t  res_lock; -        enum flow_state state; +        enum flow_state  state; -        struct timespec t0; +        struct timespec  t0;  };  struct irm {          /* FIXME: list of ipcps could be merged into the registry */ -        struct list_head ipcps; +        struct list_head    ipcps; + +        struct list_head    registry; +        pthread_rwlock_t    reg_lock; -        struct list_head registry; -        pthread_rwlock_t reg_lock; +        struct list_head    spawned_apis;          /* keep track of all flows in this processing system */ -        struct bmp * port_ids; +        struct bmp *        port_ids;          /* maps port_ids to api pair */ -        struct list_head port_map; -        pthread_rwlock_t  flows_lock; +        struct list_head    port_map; +        pthread_rwlock_t    flows_lock;          enum irm_state      state;          struct shm_du_map * dum; @@ -104,8 +111,8 @@ struct irm {          int                 sockfd;          pthread_rwlock_t    state_lock; -        pthread_t cleanup_flows; -        pthread_t shm_sanitize; +        pthread_t           cleanup_flows; +        pthread_t           shm_sanitize;  } * instance = NULL;  static struct port_map_entry * port_map_entry_create() @@ -262,9 +269,13 @@ static pid_t get_ipcp_by_dst_name(char * dst_name,  static pid_t create_ipcp(char *         name,                           enum ipcp_type ipcp_type)  { -        pid_t api; +        struct spawned_api * api;          struct ipcp_entry * tmp = NULL; +        api = malloc(sizeof(*api)); +        if (api == NULL) +                return -ENOMEM; +          pthread_rwlock_rdlock(&instance->state_lock);          if (instance->state != IRMD_RUNNING) { @@ -272,8 +283,8 @@ static pid_t create_ipcp(char *         name,                  return -1;          } -        api = ipcp_create(ipcp_type); -        if (api == -1) { +        api->api = ipcp_create(ipcp_type); +        if (api->api == -1) {                  pthread_rwlock_unlock(&instance->state_lock);                  LOG_ERR("Failed to create IPCP.");                  return -1; @@ -287,7 +298,7 @@ static pid_t create_ipcp(char *         name,          INIT_LIST_HEAD(&tmp->next); -        tmp->api = api; +        tmp->api = api->api;          tmp->name = strdup(name);          if (tmp->name  == NULL) {                  ipcp_entry_destroy(tmp); @@ -301,12 +312,30 @@ static pid_t create_ipcp(char *         name,          list_add(&tmp->next, &instance->ipcps); +        list_add(&api->next, &instance->spawned_apis); +          pthread_rwlock_unlock(&instance->reg_lock);          pthread_rwlock_unlock(&instance->state_lock); -        LOG_INFO("Created IPCP %d.", api); +        LOG_INFO("Created IPCP %d.", api->api); -        return api; +        return api->api; +} + +static void clear_spawned_api(pid_t api) +{ +        struct list_head * pos = NULL; +        struct list_head * n   = NULL; + +        list_for_each_safe(pos, n, &(instance->spawned_apis)) { +                struct spawned_api * a = +                        list_entry(pos, struct spawned_api, next); + +                if (api == a->api) { +                        list_del(&a->next); +                        free(a); +                } +        }  }  static int destroy_ipcp(pid_t api) @@ -322,6 +351,7 @@ static int destroy_ipcp(pid_t api)                          list_entry(pos, struct ipcp_entry, next);                  if (api == tmp->api) { +                        clear_spawned_api(api);                          if (ipcp_destroy(api))                                  LOG_ERR("Could not destroy IPCP.");                          list_del(&tmp->next); @@ -717,8 +747,9 @@ static struct port_map_entry * flow_accept(pid_t   api,          }          if (!reg_entry_has_api(rne, api)) { -                rgi = registry_add_ap_instance(&instance->registry, -                                               rne->name, api); +                rgi = registry_add_api_name(&instance->registry, +                                            api, +                                            rne->name);                  if (rgi == NULL) {                          pthread_rwlock_unlock(&instance->reg_lock);                          pthread_rwlock_unlock(&instance->state_lock); @@ -802,7 +833,7 @@ static int flow_alloc_resp(pid_t n_api,          pthread_mutex_lock(&rne->state_lock); -        registry_remove_ap_instance(&instance->registry, rne->name, n_api); +        registry_remove_api_name(&instance->registry, n_api, rne->name);          pthread_mutex_unlock(&rne->state_lock); @@ -1036,9 +1067,8 @@ static pid_t auto_execute(char ** argv)                  return api;          } -        if (api != 0) { +        if (api != 0)                  return api; -        }          execv(argv[0], argv); @@ -1057,6 +1087,8 @@ static struct port_map_entry * flow_req_arr(pid_t  api,          bool acc_wait = true;          enum reg_name_state state; +        struct spawned_api * c_api; +          pme = port_map_entry_create();          if (pme == NULL) {                  LOG_ERR("Failed to create port_map_entry."); @@ -1092,17 +1124,32 @@ static struct port_map_entry * flow_req_arr(pid_t  api,                  free(pme);                  return NULL;          case REG_NAME_AUTO_ACCEPT: +                c_api = malloc(sizeof(*c_api)); +                if (c_api == NULL) { +                        pthread_rwlock_unlock(&instance->reg_lock); +                        pthread_rwlock_unlock(&instance->state_lock); +                        free(pme); +                        return NULL; +                } +                  pthread_mutex_lock(&rne->state_lock);                  rne->state = REG_NAME_AUTO_EXEC;                  pthread_mutex_unlock(&rne->state_lock); -                if (auto_execute(reg_entry_resolve_auto(rne)) < 0) { +                if ((c_api->api = auto_execute(reg_entry_resolve_auto(rne))) +                    < 0) { +                        pthread_mutex_lock(&rne->state_lock); +                        rne->state = REG_NAME_AUTO_ACCEPT; +                        pthread_mutex_unlock(&rne->state_lock);                          pthread_rwlock_unlock(&instance->reg_lock);                          pthread_rwlock_unlock(&instance->state_lock);                          free(pme); +                        free(c_api);                          return NULL;                  } +                list_add(&c_api->next, &instance->spawned_apis); +                  pthread_rwlock_unlock(&instance->reg_lock);                  pthread_mutex_lock(&rne->state_lock); @@ -1228,7 +1275,6 @@ static void irm_destroy()          struct list_head * h;          struct list_head * t; -          pthread_rwlock_rdlock(&instance->state_lock);          if (instance->state != IRMD_NULL) @@ -1243,6 +1289,7 @@ static void irm_destroy()                  struct ipcp_entry * e = list_entry(h, struct ipcp_entry, next);                  list_del(&e->next);                  ipcp_destroy(e->api); +                clear_spawned_api(e->api);                  ipcp_entry_destroy(e);          } @@ -1252,6 +1299,18 @@ static void irm_destroy()                  reg_entry_destroy(e);          } +        list_for_each_safe(h, t, &instance->spawned_apis) { +                struct spawned_api * api = +                        list_entry(h, struct spawned_api, next); +                int status; +                if (kill(api->api, SIGTERM)) +                        LOG_DBGF("Could not send kill signal to %d.", api->api); +                else if (waitpid(api->api, &status, 0) < 0) +                        LOG_DBGF("Error waiting for %d to exit.", api->api); +                list_del(&api->next); +                free(api); +        } +          pthread_rwlock_unlock(&instance->reg_lock);          pthread_rwlock_wrlock(&instance->flows_lock); @@ -1260,10 +1319,8 @@ static void irm_destroy()                  struct port_map_entry * e = list_entry(h,                                                         struct port_map_entry,                                                         next); -                  list_del(&e->next);                  port_map_entry_destroy(e); -          }          if (instance->port_ids != NULL) @@ -1322,6 +1379,7 @@ void * irm_flow_cleaner()          struct timespec timeout = {IRMD_CLEANUP_TIMER / BILLION,                                     IRMD_CLEANUP_TIMER % BILLION}; +        int status;          while (true) {                  if (clock_gettime(CLOCK_MONOTONIC, &now) < 0) @@ -1383,7 +1441,7 @@ void * irm_flow_cleaner()                  pthread_rwlock_unlock(&instance->flows_lock);                  pthread_rwlock_wrlock(&instance->reg_lock); -                list_for_each_safe(pos, n, &(instance->registry)) { +                list_for_each_safe(pos, n, &instance->registry) {                          struct reg_entry * e =                                  list_entry(pos, struct reg_entry, next); @@ -1394,16 +1452,30 @@ void * irm_flow_cleaner()                                                     next);                                  if (kill(r->api, 0) < 0) {                                          LOG_INFO("Process %d gone, " -                                                 "instance deleted.", +                                                 "registry binding removed.",                                                   r->api); -                                        registry_remove_ap_instance( +                                        registry_remove_api_name(                                                  &instance->registry, -                                                e->name, -                                                r->api); +                                                r->api, +                                                e->name);                                  }                          }                  } +                list_for_each_safe(pos, n, &instance->spawned_apis) { +                        struct spawned_api * api = +                                list_entry(pos, struct spawned_api, next); +                        waitpid(api->api, &status, WNOHANG); + +                        if (kill(api->api, 0) < 0) { +                                LOG_INFO("Spawned process %d terminated " +                                         "with exit status %d.", +                                         api->api, status); +                                list_del(&api->next); +                                free(api); +                        } +                } +                  pthread_rwlock_unlock(&instance->reg_lock);                  pthread_rwlock_unlock(&instance->state_lock); @@ -1675,6 +1747,7 @@ static struct irm * irm_create()          }          INIT_LIST_HEAD(&instance->ipcps); +        INIT_LIST_HEAD(&instance->spawned_apis);          INIT_LIST_HEAD(&instance->registry);          INIT_LIST_HEAD(&instance->port_map); diff --git a/src/irmd/registry.c b/src/irmd/registry.c index a4e2fcfa..ae532d5a 100644 --- a/src/irmd/registry.c +++ b/src/irmd/registry.c @@ -491,9 +491,9 @@ int registry_remove_ap_auto(struct list_head * registry,  } -struct reg_instance * registry_add_ap_instance(struct list_head * registry, -                                               char *             name, -                                               pid_t              api) +struct reg_instance * registry_add_api_name(struct list_head * registry, +                                            pid_t              api, +                                            char *             name)  {          struct reg_entry * e    = NULL;          struct reg_instance * i = NULL; @@ -534,9 +534,9 @@ struct reg_instance * registry_add_ap_instance(struct list_head * registry,          return i;  } -int registry_remove_ap_instance(struct list_head * registry, -                                char *             name, -                                pid_t              api) +int registry_remove_api_name(struct list_head * registry, +                             pid_t              api, +                             char *             name)  {          struct reg_entry * e    = NULL;          struct reg_instance * i = NULL; diff --git a/src/irmd/registry.h b/src/irmd/registry.h index 36b68dcd..83b9d393 100644 --- a/src/irmd/registry.h +++ b/src/irmd/registry.h @@ -130,12 +130,12 @@ int                   registry_add_ap_auto(struct list_head * registry,  int                   registry_remove_ap_auto(struct list_head * registry,                                                char *             name,                                                char *             ap_name); -struct reg_instance * registry_add_ap_instance(struct list_head * registry, -                                               char *             name, -                                               pid_t              api); -int                   registry_remove_ap_instance(struct list_head * registry, -                                                  char *             name, -                                                  pid_t              api); +struct reg_instance * registry_add_api_name(struct list_head * registry, +                                            pid_t              api, +                                            char *             name); +int                   registry_remove_api_name(struct list_head * registry, +                                               pid_t              api, +                                               char *             name);  struct reg_entry *    registry_get_entry_by_name(struct list_head * registry,                                                   char *             name);  struct reg_entry *    registry_get_entry_by_ap_name(struct list_head * registry, | 
