proper shutdown
moved signal handler for SIGCHD and SIGHUP to dumm
This commit is contained in:
+1
-1
@@ -779,8 +779,8 @@ static void set_scenario(private_cowfs_t *this, char *path)
|
|||||||
static void destroy(private_cowfs_t *this)
|
static void destroy(private_cowfs_t *this)
|
||||||
{
|
{
|
||||||
fuse_exit(this->fuse);
|
fuse_exit(this->fuse);
|
||||||
pthread_join(this->thread, NULL);
|
|
||||||
fuse_unmount(this->mount, this->chan);
|
fuse_unmount(this->mount, this->chan);
|
||||||
|
pthread_join(this->thread, NULL);
|
||||||
fuse_destroy(this->fuse);
|
fuse_destroy(this->fuse);
|
||||||
free(this->mount);
|
free(this->mount);
|
||||||
free(this->master);
|
free(this->master);
|
||||||
|
|||||||
+88
-22
@@ -24,6 +24,11 @@
|
|||||||
|
|
||||||
#include "dumm.h"
|
#include "dumm.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* instances of dumm, used to deliver signals
|
||||||
|
*/
|
||||||
|
static linked_list_t *instances = NULL;
|
||||||
|
|
||||||
typedef struct private_dumm_t private_dumm_t;
|
typedef struct private_dumm_t private_dumm_t;
|
||||||
|
|
||||||
struct 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;
|
||||||
return;
|
iterator_t *iterator, *guests;
|
||||||
}
|
|
||||||
switch (info->si_code)
|
|
||||||
{
|
|
||||||
case CLD_EXITED:
|
|
||||||
case CLD_KILLED:
|
|
||||||
case CLD_DUMPED:
|
|
||||||
{
|
|
||||||
iterator_t *iterator;
|
|
||||||
guest_t *guest;
|
|
||||||
|
|
||||||
iterator = this->guests->create_iterator(this->guests, TRUE);
|
if (sig == SIGCHLD)
|
||||||
while (iterator->iterate(iterator, (void**)&guest))
|
{
|
||||||
|
iterator = instances->create_iterator(instances, TRUE);
|
||||||
|
while (iterator->iterate(iterator, (void**)&this))
|
||||||
|
{
|
||||||
|
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;
|
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**)¤t))
|
||||||
|
{
|
||||||
|
if (current == this)
|
||||||
|
{
|
||||||
|
iterator->remove(iterator);
|
||||||
break;
|
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->destroying = TRUE;
|
||||||
this->guests->destroy_offset(this->guests, offsetof(guest_t, destroy));
|
this->guests->destroy_offset(this->guests, offsetof(guest_t, destroy));
|
||||||
free(this->dir);
|
free(this->dir);
|
||||||
|
remove_instance(this);
|
||||||
free(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_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 = (bridge_t*(*)(dumm_t*, char *name))create_bridge;
|
||||||
this->public.create_bridge_iterator = (iterator_t*(*)(dumm_t*))create_bridge_iterator;
|
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->public.destroy = (void(*)(dumm_t*))destroy;
|
||||||
|
|
||||||
this->destroying = FALSE;
|
this->destroying = FALSE;
|
||||||
@@ -205,6 +269,8 @@ dumm_t *dumm_create(char *dir)
|
|||||||
this->guests = linked_list_create();
|
this->guests = linked_list_create();
|
||||||
this->bridges = linked_list_create();
|
this->bridges = linked_list_create();
|
||||||
|
|
||||||
|
add_instance(this);
|
||||||
|
|
||||||
load_guests(this);
|
load_guests(this);
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-12
@@ -30,6 +30,8 @@ typedef struct dumm_t dumm_t;
|
|||||||
* @brief dumm - Dynamic Uml Mesh Modeler
|
* @brief dumm - Dynamic Uml Mesh Modeler
|
||||||
*
|
*
|
||||||
* Controls a group of UML guests and their networks.
|
* 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 {
|
struct dumm_t {
|
||||||
|
|
||||||
@@ -67,18 +69,6 @@ struct dumm_t {
|
|||||||
*/
|
*/
|
||||||
iterator_t* (*create_bridge_iterator)(dumm_t *this);
|
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
|
* @brief stop all guests and destroy the modeler
|
||||||
*/
|
*/
|
||||||
|
|||||||
+4
-4
@@ -278,12 +278,12 @@ static bool mount_unionfs(private_guest_t *this)
|
|||||||
char diff[PATH_MAX];
|
char diff[PATH_MAX];
|
||||||
char mount[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)
|
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);
|
this->cowfs = cowfs_create(master, diff, mount);
|
||||||
if (this->cowfs)
|
if (this->cowfs)
|
||||||
{
|
{
|
||||||
|
|||||||
+2
-10
@@ -401,14 +401,7 @@ static void list()
|
|||||||
*/
|
*/
|
||||||
void signal_action(int sig, siginfo_t *info, void *ucontext)
|
void signal_action(int sig, siginfo_t *info, void *ucontext)
|
||||||
{
|
{
|
||||||
if (sig == SIGCHLD)
|
printf("\nuse 'quit'\ndumm# ");
|
||||||
{
|
|
||||||
dumm->sigchild_handler(dumm, info);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("\nuse 'quit'\ndumm# ");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -450,8 +443,7 @@ int main(int argc, char *argv[])
|
|||||||
memset(&action, 0, sizeof(action));
|
memset(&action, 0, sizeof(action));
|
||||||
action.sa_sigaction = signal_action;
|
action.sa_sigaction = signal_action;
|
||||||
action.sa_flags = SA_SIGINFO;
|
action.sa_flags = SA_SIGINFO;
|
||||||
if (sigaction(SIGCHLD, &action, NULL) != 0 ||
|
if (sigaction(SIGINT, &action, NULL) != 0 ||
|
||||||
sigaction(SIGINT, &action, NULL) != 0 ||
|
|
||||||
sigaction(SIGQUIT, &action, NULL) != 0 ||
|
sigaction(SIGQUIT, &action, NULL) != 0 ||
|
||||||
sigaction(SIGTERM, &action, NULL) != 0)
|
sigaction(SIGTERM, &action, NULL) != 0)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user