aboutsummaryrefslogtreecommitdiffstats
path: root/src/dumm
diff options
context:
space:
mode:
authorMartin Willi <martin@strongswan.org>2007-08-03 11:47:20 +0000
committerMartin Willi <martin@strongswan.org>2007-08-03 11:47:20 +0000
commit5ce04046f7bcf341ed0240ca87564f3d14064188 (patch)
tree4bca1acb4981db5ceec9d54ea45ee8a486aabc2b /src/dumm
parentdfcdae033585a9686de392e7a30566ebda06bd0e (diff)
downloadstrongswan-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.c2
-rw-r--r--src/dumm/dumm.c108
-rw-r--r--src/dumm/dumm.h14
-rw-r--r--src/dumm/guest.c8
-rw-r--r--src/dumm/main.c12
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**)&current))
+ {
+ 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)
{