proper shutdown

moved signal handler for SIGCHD and SIGHUP to dumm
This commit is contained in:
Martin Willi
2007-08-03 11:47:20 +00:00
parent dfcdae0335
commit 5ce04046f7
5 changed files with 96 additions and 48 deletions
+1 -1
View 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);
+87 -21
View File
@@ -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)
private_dumm_t *this;
guest_t *guest;
iterator_t *iterator, *guests;
if (sig == SIGCHLD)
{
return;
}
switch (info->si_code)
{
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)
{
if (guest->get_pid(guest) == info->si_pid)
continue;
}
switch (info->si_code)
{
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);
}
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;
}
default:
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;
}
+2 -12
View 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 {
@@ -67,18 +69,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
*/
+4 -4
View 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)
{
+2 -10
View 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)
{