support for killing guests properly

This commit is contained in:
Martin Willi
2007-07-27 07:37:15 +00:00
parent 5b608fd7ca
commit 539a55a441
6 changed files with 135 additions and 16 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
dumm: dumm.c dumm.h guest.c guest.h iface.c iface.h mconsole.c mconsole.h main.c dumm: dumm.c dumm.h guest.c guest.h iface.c iface.h mconsole.c mconsole.h main.c
gcc -o dumm dumm.c guest.c iface.c mconsole.c main.c -lreadline -lstrongswan -I../libstrongswan/ -g -Wall gcc -o dumm dumm.c guest.c iface.c mconsole.c main.c -lreadline -lstrongswan -I../libstrongswan/ -g -O2 -Wall -Wno-format -Wno-strict-aliasing
+33
View File
@@ -41,6 +41,38 @@ static guest_t* create_guest(private_dumm_t *this, char *name, char *master, int
static iterator_t* create_guest_iterator(private_dumm_t *this) static iterator_t* create_guest_iterator(private_dumm_t *this)
{ {
return this->guests->create_iterator(this->guests, TRUE); return this->guests->create_iterator(this->guests, TRUE);
}
/**
* Implementation of dumm_t.sigchild_handler.
*/
static void sigchild_handler(private_dumm_t *this, siginfo_t *info)
{
switch (info->si_code)
{
case CLD_EXITED:
case CLD_KILLED:
case CLD_DUMPED:
case CLD_STOPPED:
{
iterator_t *iterator;
guest_t *guest;
iterator = this->guests->create_iterator(this->guests, TRUE);
while (iterator->iterate(iterator, (void**)&guest))
{
if (guest->get_pid(guest) == info->si_pid)
{
guest->sigchild(guest);
break;
}
}
iterator->destroy(iterator);
break;
}
default:
break;
}
} }
static void destroy(private_dumm_t *this) static void destroy(private_dumm_t *this)
@@ -67,6 +99,7 @@ dumm_t *dumm_create()
{ {
private_dumm_t *this = malloc_thing(private_dumm_t); private_dumm_t *this = malloc_thing(private_dumm_t);
this->public.sigchild_handler = (void(*)(dumm_t*, siginfo_t *info))sigchild_handler;
this->public.create_guest = (void*)create_guest; this->public.create_guest = (void*)create_guest;
this->public.create_guest_iterator = (void*)create_guest_iterator; this->public.create_guest_iterator = (void*)create_guest_iterator;
this->public.destroy = (void*)destroy; this->public.destroy = (void*)destroy;
+14
View File
@@ -16,6 +16,8 @@
#ifndef DUMM_H #ifndef DUMM_H
#define DUMM_H #define DUMM_H
#include <signal.h>
#include <library.h> #include <library.h>
#include <utils/linked_list.h> #include <utils/linked_list.h>
@@ -52,6 +54,18 @@ struct dumm_t {
*/ */
iterator_t* (*create_guest_iterator) (dumm_t *this); iterator_t* (*create_guest_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
*/ */
+19 -4
View File
@@ -78,7 +78,7 @@ static iface_t* create_iface(private_guest_t *this, char *name)
iterator_t *iterator; iterator_t *iterator;
iface_t *iface; iface_t *iface;
if (this->pid == 0) if (this->state != GUEST_RUNNING)
{ {
DBG1("guest '%s' not running, unable to add interface", this->name); DBG1("guest '%s' not running, unable to add interface", this->name);
return NULL; return NULL;
@@ -225,13 +225,28 @@ static bool start(private_guest_t *this, char *kernel)
*/ */
static void stop(private_guest_t *this) static void stop(private_guest_t *this)
{ {
if (this->pid) if (this->state != GUEST_STOPPED)
{ {
this->ifaces->destroy_offset(this->ifaces, offsetof(iface_t, destroy));
this->ifaces = linked_list_create();
kill(this->pid, SIGINT); kill(this->pid, SIGINT);
this->pid = 0; this->state = GUEST_STOPPING;
while (this->state == GUEST_STOPPING)
{
sched_yield();
}
} }
} }
/**
* Implementation of guest_t.sigchild.
*/
static void sigchild(private_guest_t *this)
{
this->state = GUEST_STOPPED;
this->pid = 0;
}
/** /**
* Check if directory exists, create otherwise * Check if directory exists, create otherwise
*/ */
@@ -326,7 +341,6 @@ static void destroy(private_guest_t *this)
{ {
stop(this); stop(this);
umount_unionfs(this->name); umount_unionfs(this->name);
this->ifaces->destroy_offset(this->ifaces, offsetof(iface_t, destroy));
DESTROY_IF(this->mconsole); DESTROY_IF(this->mconsole);
free(this->name); free(this->name);
free(this->master); free(this->master);
@@ -347,6 +361,7 @@ guest_t *guest_create(char *name, char *master, int mem)
this->public.create_iface_iterator = (iterator_t*(*)(guest_t*))create_iface_iterator; this->public.create_iface_iterator = (iterator_t*(*)(guest_t*))create_iface_iterator;
this->public.start = (void*)start; this->public.start = (void*)start;
this->public.stop = (void*)stop; this->public.stop = (void*)stop;
this->public.sigchild = (void(*)(guest_t*))sigchild;
this->public.destroy = (void*)destroy; this->public.destroy = (void*)destroy;
if (!makedir(HOST_DIR, name) || !makedir(MOUNT_DIR, name) || if (!makedir(HOST_DIR, name) || !makedir(MOUNT_DIR, name) ||
+6 -1
View File
@@ -100,7 +100,12 @@ struct guest_t {
* @return iterator over iface_t's * @return iterator over iface_t's
*/ */
iterator_t* (*create_iface_iterator)(guest_t *this); iterator_t* (*create_iface_iterator)(guest_t *this);
/**
* @brief Called whenever a SIGCHILD is received.
*/
void (*sigchild)(guest_t *this);
/** /**
* @brief Close and destroy a guest with all interfaces * @brief Close and destroy a guest with all interfaces
*/ */
+62 -10
View File
@@ -24,6 +24,11 @@
#include "dumm.h" #include "dumm.h"
/**
* global set of UMLs guests
*/
dumm_t *dumm;
/** /**
* show usage information (program arguments) * show usage information (program arguments)
*/ */
@@ -53,7 +58,8 @@ static void help()
*/ */
static void help_guest() static void help_guest()
{ {
printf("start [kernel=<uml-kernel>] start the guest\n"); printf("start [kernel=<uml-kernel>] start a stopped guest\n");
printf("stop stop a started guest\n");
printf("addif <name> add an interface to the guest\n"); printf("addif <name> add an interface to the guest\n");
printf("delif <name> remove the interface\n"); printf("delif <name> remove the interface\n");
printf("listif list guests interfaces\n"); printf("listif list guests interfaces\n");
@@ -171,10 +177,20 @@ static void start_guest(guest_t *guest, char *line)
} }
} }
/**
* stop (kill) an UML guest
*/
static void stop_guest(guest_t *guest, char *line)
{
printf("stopping guest '%s'...\n", guest->get_name(guest));
guest->stop(guest);
printf("guest '%s' is down\n", guest->get_name(guest));
}
/** /**
* subshell for guests * subshell for guests
*/ */
static void guest(dumm_t *dumm, char *name) static void guest(char *name)
{ {
char *line = NULL; char *line = NULL;
char prompt[32]; char prompt[32];
@@ -211,6 +227,7 @@ static void guest(dumm_t *dumm, char *name)
QUIT = 0, QUIT = 0,
HELP, HELP,
START, START,
STOP,
ADDIF, ADDIF,
DELIF, DELIF,
LISTIF, LISTIF,
@@ -219,6 +236,7 @@ static void guest(dumm_t *dumm, char *name)
[QUIT] = "quit", [QUIT] = "quit",
[HELP] = "help", [HELP] = "help",
[START] = "start", [START] = "start",
[STOP] = "stop",
[ADDIF] = "addif", [ADDIF] = "addif",
[DELIF] = "delif", [DELIF] = "delif",
[LISTIF] = "listif", [LISTIF] = "listif",
@@ -254,6 +272,9 @@ static void guest(dumm_t *dumm, char *name)
case START: case START:
start_guest(guest, pos); start_guest(guest, pos);
continue; continue;
case STOP:
stop_guest(guest, pos);
continue;
case ADDIF: case ADDIF:
add_if(guest, pos); add_if(guest, pos);
continue; continue;
@@ -274,7 +295,7 @@ static void guest(dumm_t *dumm, char *name)
/** /**
* create an UML guest * create an UML guest
*/ */
static void create_guest(dumm_t *dumm, char *line) static void create_guest(char *line)
{ {
enum { enum {
NAME = 0, NAME = 0,
@@ -330,7 +351,7 @@ static void create_guest(dumm_t *dumm, char *line)
if (dumm->create_guest(dumm, name, master, mem)) if (dumm->create_guest(dumm, name, master, mem))
{ {
printf("guest '%s' created\n", name); printf("guest '%s' created\n", name);
guest(dumm, name); guest(name);
} }
else else
{ {
@@ -341,7 +362,7 @@ static void create_guest(dumm_t *dumm, char *line)
/** /**
* list running UML guests * list running UML guests
*/ */
static void list(dumm_t *dumm) static void list()
{ {
iterator_t *guests, *ifaces; iterator_t *guests, *ifaces;
guest_t *guest; guest_t *guest;
@@ -350,7 +371,8 @@ static void list(dumm_t *dumm)
guests = dumm->create_guest_iterator(dumm); guests = dumm->create_guest_iterator(dumm);
while (guests->iterate(guests, (void**)&guest)) while (guests->iterate(guests, (void**)&guest))
{ {
printf("%s\n", guest->get_name(guest)); printf("%s (%N)\n", guest->get_name(guest),
guest_state_names, guest->get_state(guest));
ifaces = guest->create_iface_iterator(guest); ifaces = guest->create_iface_iterator(guest);
while (ifaces->iterate(ifaces, (void**)&iface)) while (ifaces->iterate(ifaces, (void**)&iface))
{ {
@@ -362,13 +384,31 @@ static void list(dumm_t *dumm)
guests->destroy(guests); guests->destroy(guests);
} }
/**
* Signal handler
*/
void signal_action(int sig, siginfo_t *info, void *ucontext)
{
if (sig == SIGCHLD)
{
dumm->sigchild_handler(dumm, info);
}
else
{
dumm->destroy(dumm);
clear_history();
printf("\n");
exit(0);
}
}
/** /**
* main routine, parses args and reads from console * main routine, parses args and reads from console
*/ */
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
dumm_t *dumm;
char *line = NULL; char *line = NULL;
struct sigaction action;
while (TRUE) while (TRUE)
{ {
@@ -400,6 +440,18 @@ int main(int argc, char *argv[])
} }
dumm = dumm_create(); dumm = dumm_create();
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 ||
sigaction(SIGQUIT, &action, NULL) != 0 ||
sigaction(SIGTERM, &action, NULL) != 0)
{
printf("signal handler setup failed: %m.\n");
return 1;
}
while (TRUE) while (TRUE)
{ {
@@ -447,13 +499,13 @@ int main(int argc, char *argv[])
help(); help();
continue; continue;
case CREATE: case CREATE:
create_guest(dumm, pos); create_guest(pos);
continue; continue;
case LIST: case LIST:
list(dumm); list();
continue; continue;
case GUEST: case GUEST:
guest(dumm, pos); guest(pos);
continue; continue;
default: default:
printf("command unknown: '%s'\n", line); printf("command unknown: '%s'\n", line);