diff options
author | Martin Willi <martin@strongswan.org> | 2007-08-03 11:47:20 +0000 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2007-08-03 11:47:20 +0000 |
commit | 5ce04046f7bcf341ed0240ca87564f3d14064188 (patch) | |
tree | 4bca1acb4981db5ceec9d54ea45ee8a486aabc2b /src/dumm | |
parent | dfcdae033585a9686de392e7a30566ebda06bd0e (diff) | |
download | strongswan-5ce04046f7bcf341ed0240ca87564f3d14064188.tar.bz2 strongswan-5ce04046f7bcf341ed0240ca87564f3d14064188.tar.xz |
proper shutdown
moved signal handler for SIGCHD and SIGHUP to dumm
Diffstat (limited to 'src/dumm')
-rw-r--r-- | src/dumm/cowfs.c | 2 | ||||
-rw-r--r-- | src/dumm/dumm.c | 108 | ||||
-rw-r--r-- | src/dumm/dumm.h | 14 | ||||
-rw-r--r-- | src/dumm/guest.c | 8 | ||||
-rw-r--r-- | src/dumm/main.c | 12 |
5 files changed, 96 insertions, 48 deletions
diff --git a/src/dumm/cowfs.c b/src/dumm/cowfs.c index f3b169b7c..6e0fa9222 100644 --- a/src/dumm/cowfs.c +++ b/src/dumm/cowfs.c @@ -779,8 +779,8 @@ static void set_scenario(private_cowfs_t *this, char *path) static void destroy(private_cowfs_t *this) { fuse_exit(this->fuse); - pthread_join(this->thread, NULL); fuse_unmount(this->mount, this->chan); + pthread_join(this->thread, NULL); fuse_destroy(this->fuse); free(this->mount); free(this->master); diff --git a/src/dumm/dumm.c b/src/dumm/dumm.c index b8211ff9e..486e8d380 100644 --- a/src/dumm/dumm.c +++ b/src/dumm/dumm.c @@ -24,6 +24,11 @@ #include "dumm.h" +/** + * instances of dumm, used to deliver signals + */ +static linked_list_t *instances = NULL; + typedef struct private_dumm_t private_dumm_t; struct private_dumm_t { @@ -87,37 +92,96 @@ static iterator_t* create_bridge_iterator(private_dumm_t *this) } /** - * Implementation of dumm_t.sigchild_handler. + * signal handler */ -static void sigchild_handler(private_dumm_t *this, siginfo_t *info) +void signal_handler(int sig, siginfo_t *info, void *ucontext) { - if (this->destroying) - { - return; - } - switch (info->si_code) + private_dumm_t *this; + guest_t *guest; + iterator_t *iterator, *guests; + + if (sig == SIGCHLD) { - case CLD_EXITED: - case CLD_KILLED: - case CLD_DUMPED: + iterator = instances->create_iterator(instances, TRUE); + while (iterator->iterate(iterator, (void**)&this)) { - iterator_t *iterator; - guest_t *guest; - - iterator = this->guests->create_iterator(this->guests, TRUE); - while (iterator->iterate(iterator, (void**)&guest)) + if (this->destroying) + { + continue; + } + switch (info->si_code) { - if (guest->get_pid(guest) == info->si_pid) + case CLD_EXITED: + case CLD_KILLED: + case CLD_DUMPED: { - guest->sigchild(guest); + guests = this->guests->create_iterator(this->guests, TRUE); + while (guests->iterate(guests, (void**)&guest)) + { + if (guest->get_pid(guest) == info->si_pid) + { + guest->sigchild(guest); + break; + } + } + guests->destroy(guests); break; } + default: + break; } - iterator->destroy(iterator); - break; } - default: + iterator->destroy(iterator); + } + /* SIGHUP is currently just ignored */ +} + +/** + * add a dumm instance + */ +static void add_instance(private_dumm_t *this) +{ + if (instances == NULL) + { + struct sigaction action; + + instances = linked_list_create(); + + memset(&action, 0, sizeof(action)); + action.sa_sigaction = signal_handler; + action.sa_flags = SA_SIGINFO; + + if (sigaction(SIGCHLD, &action, NULL) != 0 || + sigaction(SIGHUP, &action, NULL) != 0) + { + DBG1("installing signal handler failed!"); + } + } + instances->insert_last(instances, this); +} + +/** + * remove a dumm instance + */ +static void remove_instance(private_dumm_t *this) +{ + iterator_t *iterator; + private_dumm_t *current; + + iterator = instances->create_iterator(instances, TRUE); + while (iterator->iterate(iterator, (void**)¤t)) + { + if (current == this) + { + iterator->remove(iterator); break; + } + } + iterator->destroy(iterator); + if (instances->get_count(instances) == 0) + { + instances->destroy(instances); + instances = NULL; } } @@ -141,6 +205,7 @@ static void destroy(private_dumm_t *this) this->destroying = TRUE; this->guests->destroy_offset(this->guests, offsetof(guest_t, destroy)); free(this->dir); + remove_instance(this); free(this); } @@ -190,7 +255,6 @@ dumm_t *dumm_create(char *dir) this->public.create_guest_iterator = (iterator_t*(*)(dumm_t*))create_guest_iterator; this->public.create_bridge = (bridge_t*(*)(dumm_t*, char *name))create_bridge; this->public.create_bridge_iterator = (iterator_t*(*)(dumm_t*))create_bridge_iterator; - this->public.sigchild_handler = (void(*)(dumm_t*, siginfo_t *info))sigchild_handler; this->public.destroy = (void(*)(dumm_t*))destroy; this->destroying = FALSE; @@ -205,6 +269,8 @@ dumm_t *dumm_create(char *dir) this->guests = linked_list_create(); this->bridges = linked_list_create(); + add_instance(this); + load_guests(this); return &this->public; } diff --git a/src/dumm/dumm.h b/src/dumm/dumm.h index cb68fdb1e..dea5f3428 100644 --- a/src/dumm/dumm.h +++ b/src/dumm/dumm.h @@ -30,6 +30,8 @@ typedef struct dumm_t dumm_t; * @brief dumm - Dynamic Uml Mesh Modeler * * Controls a group of UML guests and their networks. + * Dumm catches SIGCHD and SIGHUP to trace UML child processes and the FUSE + * filesystem. Do not overwrite these signal handlers! */ struct dumm_t { @@ -68,18 +70,6 @@ struct dumm_t { iterator_t* (*create_bridge_iterator)(dumm_t *this); /** - * @brief Handler for received SIG_CHILD signals. - * - * Dumm spans children, UML kernels. To track and cleanup these kernel - * processes, it is required that this method is called whenever a SIG_CHILD - * is received. The user is responsible to call sigchild_handler on each - * dumm_t instance with the signals siginfo_t. - * - * @param info siginfo associated to the SIG_CHILD signal - */ - void (*sigchild_handler)(dumm_t *this, siginfo_t *info); - - /** * @brief stop all guests and destroy the modeler */ void (*destroy) (dumm_t *this); diff --git a/src/dumm/guest.c b/src/dumm/guest.c index 6ba14e028..55d4f12b5 100644 --- a/src/dumm/guest.c +++ b/src/dumm/guest.c @@ -277,13 +277,13 @@ static bool mount_unionfs(private_guest_t *this) char master[PATH_MAX]; char diff[PATH_MAX]; char mount[PATH_MAX]; - - snprintf(master, sizeof(master), "%s/%s", this->dirname, MASTER_DIR); - snprintf(diff, sizeof(diff), "%s/%s", this->dirname, DIFF_DIR); - snprintf(mount, sizeof(mount), "%s/%s", this->dirname, UNION_DIR); if (this->cowfs == NULL) { + snprintf(master, sizeof(master), "%s/%s", this->dirname, MASTER_DIR); + snprintf(diff, sizeof(diff), "%s/%s", this->dirname, DIFF_DIR); + snprintf(mount, sizeof(mount), "%s/%s", this->dirname, UNION_DIR); + this->cowfs = cowfs_create(master, diff, mount); if (this->cowfs) { diff --git a/src/dumm/main.c b/src/dumm/main.c index bd764017a..aca5967c2 100644 --- a/src/dumm/main.c +++ b/src/dumm/main.c @@ -401,14 +401,7 @@ static void list() */ void signal_action(int sig, siginfo_t *info, void *ucontext) { - if (sig == SIGCHLD) - { - dumm->sigchild_handler(dumm, info); - } - else - { - printf("\nuse 'quit'\ndumm# "); - } + printf("\nuse 'quit'\ndumm# "); } /** @@ -450,8 +443,7 @@ int main(int argc, char *argv[]) memset(&action, 0, sizeof(action)); action.sa_sigaction = signal_action; action.sa_flags = SA_SIGINFO; - if (sigaction(SIGCHLD, &action, NULL) != 0 || - sigaction(SIGINT, &action, NULL) != 0 || + if (sigaction(SIGINT, &action, NULL) != 0 || sigaction(SIGQUIT, &action, NULL) != 0 || sigaction(SIGTERM, &action, NULL) != 0) { |