--- libvirt-0.9.13/src/lxc/lxc_controller.c.orig 2012-06-25 09:06:18.000000000 +0200 +++ libvirt-0.9.13/src/lxc/lxc_controller.c 2012-07-08 11:48:06.949684744 +0200 @@ -44,6 +44,7 @@ #include #include #include +#include #if HAVE_CAPNG # include @@ -558,6 +559,7 @@ return ret; } +static virCgroupPtr domain_cgroup = NULL; /** * lxcSetContainerResources @@ -617,10 +619,13 @@ _("Unable to add task %d to cgroup for domain %s"), getpid(), def->name); } + domain_cgroup = cgroup; + goto out; cleanup: - virCgroupFree(&driver); virCgroupFree(&cgroup); +out: + virCgroupFree(&driver); return rc; } @@ -709,6 +714,63 @@ static bool quit = false; static virMutex lock; static int sigpipe[2]; +static pid_t initpid = -1; + +static void lxcSignalALRMHandler(int signum ATTRIBUTE_UNUSED) +{ + int tasks = 0; + char *keypath = NULL; + int rc = -1; + FILE *fp; + + if (initpid <= 0) + return; + if (domain_cgroup == NULL) + return; + + rc = virCgroupPathOfController(domain_cgroup, -1, "tasks", &keypath); + if (rc != 0) { + VIR_DEBUG("No path of cgroup tasks"); + return; + } + + if (!(fp = fopen(keypath, "r"))) { + VIR_DEBUG("Failed to read %s: %m\n", keypath); + return; + } + while (!feof(fp)) { + unsigned long pid_value; + if (fscanf(fp, "%lu", &pid_value) != 1) { + if (feof(fp)) + break; + rc = -errno; + VIR_DEBUG("Failed to read %s: %m\n", keypath); + fclose(fp); + return; + } + tasks++; + } + fclose(fp); + VIR_DEBUG("Tasks left: %d", tasks); + /* Kill init if it's the only process left beside container controller process */ + if (tasks == 2) + kill(initpid, SIGKILL); +} + +static void lxcSignalINTHandler(int signum ATTRIBUTE_UNUSED) +{ + struct itimerval timer; + + if (initpid <= 0) + return; + kill(initpid, SIGINT); + + timer.it_interval.tv_sec = 1; + timer.it_interval.tv_usec = 0; + timer.it_value.tv_sec = 1; + timer.it_value.tv_usec = 0; + setitimer(ITIMER_REAL, &timer, NULL); +} static void lxcSignalChildHandler(int signum ATTRIBUTE_UNUSED) { @@ -1134,6 +1196,18 @@ goto cleanup; } + if (signal(SIGINT, lxcSignalINTHandler) == SIG_ERR) { + virReportSystemError(errno, "%s", + _("Cannot install signal handler")); + goto cleanup; + } + + if (signal(SIGALRM, lxcSignalALRMHandler) == SIG_ERR) { + virReportSystemError(errno, "%s", + _("Cannot install signal handler")); + goto cleanup; + } + VIR_DEBUG("serverFd=%d clientFd=%d", serverFd, clientFd); virResetLastError(); @@ -1539,6 +1613,7 @@ goto cleanup; VIR_FORCE_CLOSE(control[1]); VIR_FORCE_CLOSE(containerhandshake[1]); + initpid = container; if (lxcControllerMoveInterfaces(nveths, veths, container) < 0) goto cleanup; diff -ur libvirt-0.9.12/src/lxc/lxc_driver.c libvirt-0.9.12-lxc/src/lxc/lxc_driver.c --- libvirt-0.9.12/src/lxc/lxc_driver.c 2012-05-02 05:08:53.000000000 +0200 +++ libvirt-0.9.12-lxc/src/lxc/lxc_driver.c 2012-05-16 19:54:48.946901077 +0200 @@ -3751,6 +3751,58 @@ } static int +lxcDomainShutdown (virDomainPtr dom) +{ + lxc_driver_t *driver = dom->conn->privateData; + virDomainObjPtr vm; + virDomainEventPtr event = NULL; + int ret = -1; + + lxcDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + lxcError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + if (!virDomainObjIsActive(vm)) { + lxcError(VIR_ERR_OPERATION_INVALID, + "%s", _("Domain is not running")); + goto cleanup; + } + + if (vm->pid <= 0) { + lxcError(VIR_ERR_INTERNAL_ERROR, + _("Invalid PID %d for container"), vm->pid); + goto cleanup; + } + + if (kill(vm->pid, SIGINT) < -1) + goto cleanup; + ret = 0; + + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); + virDomainAuditStop(vm, "shutdown"); + if (!vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } + +cleanup: + if (vm) + virDomainObjUnlock(vm); + if (event) + lxcDomainEventQueue(driver, event); + lxcDriverUnlock(driver); + return ret; +} + +static int lxcDomainOpenConsole(virDomainPtr dom, const char *dev_name, virStreamPtr st, @@ -3866,6 +3918,7 @@ .domainLookupByName = lxcDomainLookupByName, /* 0.4.2 */ .domainSuspend = lxcDomainSuspend, /* 0.7.2 */ .domainResume = lxcDomainResume, /* 0.7.2 */ + .domainShutdown = lxcDomainShutdown, /* PLD */ .domainDestroy = lxcDomainDestroy, /* 0.4.4 */ .domainDestroyFlags = lxcDomainDestroyFlags, /* 0.9.4 */ .domainGetOSType = lxcGetOSType, /* 0.4.2 */