proper shutdown
authorMartin Willi <martin@strongswan.org>
Fri, 3 Aug 2007 11:47:20 +0000 (11:47 -0000)
committerMartin Willi <martin@strongswan.org>
Fri, 3 Aug 2007 11:47:20 +0000 (11:47 -0000)
moved signal handler for SIGCHD and SIGHUP to dumm

src/dumm/cowfs.c
src/dumm/dumm.c
src/dumm/dumm.h
src/dumm/guest.c
src/dumm/main.c

index f3b169b..6e0fa92 100644 (file)
@@ -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);
index b8211ff..486e8d3 100644 (file)
 
 #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;
 }
index cb68fdb..dea5f34 100644 (file)
@@ -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);
index 6ba14e0..55d4f12 100644 (file)
@@ -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)
                {
index bd76401..aca5967 100644 (file)
@@ -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)
        {