mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-26 18:41:17 +00:00
Fix a few issues related to restart of libvirtd with containers running.
Mon May 12 23:32:21 PST 2008 David L. Leskovec <dlesko@linux.vnet.ibm.com> * src/lxc_driver.c: Add sanity of tty pid before kill() Ignore ECHILD errors during VM cleanup Call functions to store tty pid and cleanup tty pid file * src/lxc_conf.h: Add function to verify container process exists Add facilities to manage storing the tty forward process pid * src/lxc_conf.c: Add function to verify container process exists Call function to verify container process during config load Add facilities to manage storing the tty forward process pid Call function to load tty pid during load config
This commit is contained in:
parent
eeb224b812
commit
0bd57cdbe1
12
ChangeLog
12
ChangeLog
@ -1,3 +1,15 @@
|
||||
Wed Jun 4 23:02:21 PST 2008 David L. Leskovec <dlesko@linux.vnet.ibm.com>
|
||||
|
||||
* src/lxc_driver.c: Add sanity of tty pid before kill()
|
||||
Ignore ECHILD errors during VM cleanup
|
||||
Call functions to store tty pid and cleanup tty pid file
|
||||
* src/lxc_conf.h: Add function to verify container process exists
|
||||
Add facilities to manage storing the tty forward process pid
|
||||
* src/lxc_conf.c: Add function to verify container process exists
|
||||
Call function to verify container process during config load
|
||||
Add facilities to manage storing the tty forward process pid
|
||||
Call function to load tty pid during load config
|
||||
|
||||
Tue Jun 3 08:58:00 BST 2008 Richard W.M. Jones <rjones@redhat.com>
|
||||
|
||||
* src/xm_internal.c: If vcpu cpuset attribute is invalid
|
||||
|
224
src/lxc_conf.c
224
src/lxc_conf.c
@ -348,6 +348,12 @@ static lxc_vm_def_t * lxcParseXML(virConnectPtr conn, xmlDocPtr docPtr)
|
||||
_("invalid domain id"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* verify the container process still exists */
|
||||
if (1 != lxcCheckContainerProcess(containerDef)) {
|
||||
containerDef->id = -1;
|
||||
}
|
||||
|
||||
} else {
|
||||
containerDef->id = -1;
|
||||
}
|
||||
@ -458,6 +464,46 @@ lxc_vm_t * lxcAssignVMDef(virConnectPtr conn,
|
||||
return vm;
|
||||
}
|
||||
|
||||
/**
|
||||
* lxcCheckContainerProcess:
|
||||
* @def: Ptr to VM definition
|
||||
*
|
||||
* Checks if the container process (stored at def->id is running
|
||||
*
|
||||
* Returns on success or -1 in case of error
|
||||
* 0 - no process with id vm->def->id
|
||||
* 1 - container process exists
|
||||
* -1 - error
|
||||
*/
|
||||
int lxcCheckContainerProcess(lxc_vm_def_t *def)
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
if (1 < def->id) {
|
||||
if (-1 == kill(def->id, 0)) {
|
||||
if (ESRCH == errno) {
|
||||
rc = 0;
|
||||
DEBUG("pid %d no longer exists", def->id);
|
||||
goto done;
|
||||
}
|
||||
|
||||
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("error checking container process: %d %s"),
|
||||
def->id, strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
|
||||
DEBUG("pid %d still exists", def->id);
|
||||
rc = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
|
||||
done:
|
||||
return rc;
|
||||
}
|
||||
|
||||
void lxcRemoveInactiveVM(lxc_driver_t *driver,
|
||||
lxc_vm_t *vm)
|
||||
{
|
||||
@ -602,6 +648,10 @@ static lxc_vm_t * lxcLoadConfig(lxc_driver_t *driver,
|
||||
strncpy(vm->configFileBase, file, PATH_MAX);
|
||||
vm->configFile[PATH_MAX-1] = '\0';
|
||||
|
||||
if (lxcLoadTtyPid(driver, vm) < 0) {
|
||||
DEBUG0("failed to load tty pid");
|
||||
}
|
||||
|
||||
return vm;
|
||||
}
|
||||
|
||||
@ -614,6 +664,8 @@ int lxcLoadDriverConfig(lxc_driver_t *driver)
|
||||
return -1;
|
||||
}
|
||||
|
||||
driver->stateDir = strdup(LOCAL_STATE_DIR "/run/libvirt/lxc");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -835,4 +887,176 @@ int lxcDeleteConfig(virConnectPtr conn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* lxcStoreTtyPid:
|
||||
* @driver: pointer to driver
|
||||
* @vm: Ptr to VM
|
||||
*
|
||||
* Stores the pid of the tty forward process contained in vm->pid
|
||||
* LOCAL_STATE_DIR/run/libvirt/lxc/{container_name}.pid
|
||||
*
|
||||
* Returns 0 on success or -1 in case of error
|
||||
*/
|
||||
int lxcStoreTtyPid(const lxc_driver_t *driver, lxc_vm_t *vm)
|
||||
{
|
||||
int rc = -1;
|
||||
int fd;
|
||||
FILE *file = NULL;
|
||||
|
||||
if (vm->ttyPidFile[0] == 0x00) {
|
||||
if ((rc = virFileMakePath(driver->stateDir))) {
|
||||
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot create lxc state directory %s: %s"),
|
||||
driver->stateDir, strerror(rc));
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (virFileBuildPath(driver->stateDir, vm->def->name, ".pid",
|
||||
vm->ttyPidFile, PATH_MAX) < 0) {
|
||||
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot construct tty pid file path"));
|
||||
goto error_out;
|
||||
}
|
||||
}
|
||||
|
||||
if ((fd = open(vm->ttyPidFile,
|
||||
O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR)) < 0) {
|
||||
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot create tty pid file %s: %s"),
|
||||
vm->ttyPidFile, strerror(errno));
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (!(file = fdopen(fd, "w"))) {
|
||||
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot fdopen tty pid file %s: %s"),
|
||||
vm->ttyPidFile, strerror(errno));
|
||||
|
||||
if (close(fd) < 0) {
|
||||
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("failed to close tty pid file %s: %s"),
|
||||
vm->ttyPidFile, strerror(errno));
|
||||
}
|
||||
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (fprintf(file, "%d", vm->pid) < 0) {
|
||||
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot write tty pid file %s: %s"),
|
||||
vm->ttyPidFile, strerror(errno));
|
||||
|
||||
goto fclose_error_out;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
|
||||
fclose_error_out:
|
||||
if (fclose(file) < 0) {
|
||||
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("failed to close tty pid file %s: %s"),
|
||||
vm->ttyPidFile, strerror(errno));
|
||||
}
|
||||
|
||||
error_out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* lxcLoadTtyPid:
|
||||
* @driver: pointer to driver
|
||||
* @vm: Ptr to VM
|
||||
*
|
||||
* Loads the pid of the tty forward process from the pid file.
|
||||
* LOCAL_STATE_DIR/run/libvirt/lxc/{container_name}.pid
|
||||
*
|
||||
* Returns
|
||||
* > 0 - pid of tty process
|
||||
* 0 - no tty pid file
|
||||
* -1 - error
|
||||
*/
|
||||
int lxcLoadTtyPid(const lxc_driver_t *driver, lxc_vm_t *vm)
|
||||
{
|
||||
int rc = -1;
|
||||
FILE *file;
|
||||
|
||||
if (vm->ttyPidFile[0] == 0x00) {
|
||||
if ((rc = virFileMakePath(driver->stateDir))) {
|
||||
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot create lxc state directory %s: %s"),
|
||||
driver->stateDir, strerror(rc));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (virFileBuildPath(driver->stateDir, vm->def->name, ".pid",
|
||||
vm->ttyPidFile, PATH_MAX) < 0) {
|
||||
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot construct tty pid file path"));
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(file = fopen(vm->ttyPidFile, "r"))) {
|
||||
if (ENOENT == errno) {
|
||||
rc = 0;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot open tty pid file %s: %s"),
|
||||
vm->ttyPidFile, strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (fscanf(file, "%d", &(vm->pid)) < 0) {
|
||||
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot read tty pid file %s: %s"),
|
||||
vm->ttyPidFile, strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (fclose(file) < 0) {
|
||||
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("failed to close tty pid file %s: %s"),
|
||||
vm->ttyPidFile, strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = vm->pid;
|
||||
|
||||
cleanup:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* lxcDeleteTtyPid:
|
||||
* @vm: Ptr to VM
|
||||
*
|
||||
* Unlinks the tty pid file for the vm
|
||||
* LOCAL_STATE_DIR/run/libvirt/lxc/{container_name}.pid
|
||||
*
|
||||
* Returns on 0 success or -1 in case of error
|
||||
*/
|
||||
int lxcDeleteTtyPidFile(const lxc_vm_t *vm)
|
||||
{
|
||||
if (vm->ttyPidFile[0] == 0x00) {
|
||||
goto no_file;
|
||||
}
|
||||
|
||||
if (unlink(vm->ttyPidFile) < 0) {
|
||||
if (errno == ENOENT) {
|
||||
goto no_file;
|
||||
}
|
||||
|
||||
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot remove ttyPidFile %s: %s"), vm->ttyPidFile,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
no_file:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* WITH_LXC */
|
||||
|
@ -71,6 +71,8 @@ struct __lxc_vm {
|
||||
char configFile[PATH_MAX];
|
||||
char configFileBase[PATH_MAX];
|
||||
|
||||
char ttyPidFile[PATH_MAX];
|
||||
|
||||
int parentTty;
|
||||
int containerTtyFd;
|
||||
char *containerTty;
|
||||
@ -86,6 +88,7 @@ struct __lxc_driver {
|
||||
int nactivevms;
|
||||
int ninactivevms;
|
||||
char* configDir;
|
||||
char* stateDir;
|
||||
};
|
||||
|
||||
/* Types and structs */
|
||||
@ -124,6 +127,7 @@ lxc_vm_t *lxcFindVMByUUID(const lxc_driver_t *driver,
|
||||
const unsigned char *uuid);
|
||||
lxc_vm_t *lxcFindVMByName(const lxc_driver_t *driver,
|
||||
const char *name);
|
||||
int lxcCheckContainerProcess(lxc_vm_def_t *vm);
|
||||
void lxcRemoveInactiveVM(lxc_driver_t *driver,
|
||||
lxc_vm_t *vm);
|
||||
void lxcFreeVMs(lxc_vm_t *vms);
|
||||
@ -133,6 +137,9 @@ int lxcDeleteConfig(virConnectPtr conn,
|
||||
lxc_driver_t *driver,
|
||||
const char *configFile,
|
||||
const char *name);
|
||||
int lxcStoreTtyPid(const lxc_driver_t *driver, lxc_vm_t *vm);
|
||||
int lxcLoadTtyPid(const lxc_driver_t *driver, lxc_vm_t *vm);
|
||||
int lxcDeleteTtyPidFile(const lxc_vm_t *vm);
|
||||
|
||||
void lxcError(virConnectPtr conn,
|
||||
virDomainPtr dom,
|
||||
|
@ -328,6 +328,8 @@ static int lxcDomainUndefine(virDomainPtr dom)
|
||||
|
||||
vm->configFile[0] = '\0';
|
||||
|
||||
lxcDeleteTtyPidFile(vm);
|
||||
|
||||
lxcRemoveInactiveVM(driver, vm);
|
||||
|
||||
return 0;
|
||||
@ -798,6 +800,10 @@ static int lxcVmStart(virConnectPtr conn,
|
||||
lxcTtyForward(vm->parentTty, vm->containerTtyFd);
|
||||
}
|
||||
|
||||
if (lxcStoreTtyPid(driver, vm)) {
|
||||
DEBUG0("unable to store tty pid");
|
||||
}
|
||||
|
||||
close(vm->parentTty);
|
||||
close(vm->containerTtyFd);
|
||||
|
||||
@ -943,7 +949,7 @@ static int lxcVMCleanup(lxc_driver_t *driver, lxc_vm_t * vm)
|
||||
while (((waitRc = waitpid(vm->def->id, &childStatus, 0)) == -1) &&
|
||||
errno == EINTR);
|
||||
|
||||
if (waitRc != vm->def->id) {
|
||||
if ((waitRc != vm->def->id) && (errno != ECHILD)) {
|
||||
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("waitpid failed to wait for container %d: %d %s"),
|
||||
vm->def->id, waitRc, strerror(errno));
|
||||
@ -958,6 +964,11 @@ static int lxcVMCleanup(lxc_driver_t *driver, lxc_vm_t * vm)
|
||||
}
|
||||
|
||||
kill_tty:
|
||||
if (2 > vm->pid) {
|
||||
DEBUG("not killing tty process with pid %d", vm->pid);
|
||||
goto tty_error_out;
|
||||
}
|
||||
|
||||
if (0 > (kill(vm->pid, SIGKILL))) {
|
||||
if (ESRCH != errno) {
|
||||
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
@ -971,7 +982,7 @@ kill_tty:
|
||||
while (((waitRc = waitpid(vm->pid, &childStatus, 0)) == -1) &&
|
||||
errno == EINTR);
|
||||
|
||||
if (waitRc != vm->pid) {
|
||||
if ((waitRc != vm->pid) && (errno != ECHILD)) {
|
||||
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("waitpid failed to wait for tty %d: %d %s"),
|
||||
vm->pid, waitRc, strerror(errno));
|
||||
@ -980,6 +991,7 @@ kill_tty:
|
||||
tty_error_out:
|
||||
vm->state = VIR_DOMAIN_SHUTOFF;
|
||||
vm->pid = -1;
|
||||
lxcDeleteTtyPidFile(vm);
|
||||
vm->def->id = -1;
|
||||
driver->nactivevms--;
|
||||
driver->ninactivevms++;
|
||||
@ -1063,6 +1075,7 @@ static int lxcStartup(void)
|
||||
static void lxcFreeDriver(lxc_driver_t *driver)
|
||||
{
|
||||
free(driver->configDir);
|
||||
free(driver->stateDir);
|
||||
free(driver);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user