1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-03-07 17:28:15 +00:00

Convert the virCgroupKill* APIs to report errors

Instead of returning errno values, change the virCgroupKill*
APIs to fully report errors.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrange 2013-07-19 15:43:04 +01:00
parent b64dabff27
commit 3260fdfab0
2 changed files with 67 additions and 62 deletions

View File

@ -693,17 +693,12 @@ int virLXCProcessStop(virLXCDriverPtr driver,
if (priv->cgroup) { if (priv->cgroup) {
rc = virCgroupKillPainfully(priv->cgroup); rc = virCgroupKillPainfully(priv->cgroup);
if (rc < 0) { if (rc < 0)
virReportSystemError(-rc, "%s", return -1;
_("Failed to kill container PIDs")); if (rc > 0) {
rc = -1;
goto cleanup;
}
if (rc == 1) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Some container PIDs refused to die")); _("Some processes refused to die"));
rc = -1; return -1;
goto cleanup;
} }
} else { } else {
/* If cgroup doesn't exist, the VM pids must have already /* If cgroup doesn't exist, the VM pids must have already
@ -713,10 +708,7 @@ int virLXCProcessStop(virLXCDriverPtr driver,
virLXCProcessCleanup(driver, vm, reason); virLXCProcessCleanup(driver, vm, reason);
rc = 0; return 0;
cleanup:
return rc;
} }

View File

@ -2355,9 +2355,12 @@ int virCgroupGetFreezerState(virCgroupPtr group, char **state)
#if defined HAVE_KILL && defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R #if defined HAVE_KILL && defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
/*
* Returns 1 if some PIDs are killed, 0 if none are killed, or -1 on error
*/
static int virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr pids) static int virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr pids)
{ {
int rc; int ret = -1;
bool killedAny = false; bool killedAny = false;
char *keypath = NULL; char *keypath = NULL;
bool done = false; bool done = false;
@ -2365,10 +2368,11 @@ static int virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr
VIR_DEBUG("group=%p path=%s signum=%d pids=%p", VIR_DEBUG("group=%p path=%s signum=%d pids=%p",
group, group->path, signum, pids); group, group->path, signum, pids);
rc = virCgroupPathOfController(group, -1, "tasks", &keypath); if (virCgroupPathOfController(group, -1, "tasks", &keypath) < 0) {
if (rc != 0) { virReportError(VIR_ERR_INTERNAL_ERROR,
VIR_DEBUG("No path of %s, tasks", group->path); _("No tasks file for group path '%s'"),
return rc; group->path);
return -1;
} }
/* PIDs may be forking as we kill them, so loop /* PIDs may be forking as we kill them, so loop
@ -2377,8 +2381,9 @@ static int virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr
while (!done) { while (!done) {
done = true; done = true;
if (!(fp = fopen(keypath, "r"))) { if (!(fp = fopen(keypath, "r"))) {
rc = -errno; virReportSystemError(errno,
VIR_DEBUG("Failed to read %s: %m\n", keypath); _("Failed to read %s"),
keypath);
goto cleanup; goto cleanup;
} else { } else {
while (!feof(fp)) { while (!feof(fp)) {
@ -2386,8 +2391,9 @@ static int virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr
if (fscanf(fp, "%lu", &pid_value) != 1) { if (fscanf(fp, "%lu", &pid_value) != 1) {
if (feof(fp)) if (feof(fp))
break; break;
rc = -errno; virReportSystemError(errno,
VIR_DEBUG("Failed to read %s: %m\n", keypath); _("Failed to read %s"),
keypath);
goto cleanup; goto cleanup;
} }
if (virHashLookup(pids, (void*)pid_value)) if (virHashLookup(pids, (void*)pid_value))
@ -2397,7 +2403,9 @@ static int virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr
/* Cgroups is a Linux concept, so this cast is safe. */ /* Cgroups is a Linux concept, so this cast is safe. */
if (kill((pid_t)pid_value, signum) < 0) { if (kill((pid_t)pid_value, signum) < 0) {
if (errno != ESRCH) { if (errno != ESRCH) {
rc = -errno; virReportSystemError(errno,
_("Failed to kill process %lu"),
pid_value);
goto cleanup; goto cleanup;
} }
/* Leave RC == 0 since we didn't kill one */ /* Leave RC == 0 since we didn't kill one */
@ -2412,13 +2420,13 @@ static int virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr
} }
} }
rc = killedAny ? 1 : 0; ret = killedAny ? 1 : 0;
cleanup: cleanup:
VIR_FREE(keypath); VIR_FREE(keypath);
VIR_FORCE_FCLOSE(fp); VIR_FORCE_FCLOSE(fp);
return rc; return ret;
} }
@ -2437,15 +2445,12 @@ static void *virCgroupPidCopy(const void *name)
} }
/* /*
* Returns * Returns 1 if some PIDs are killed, 0 if none are killed, or -1 on error
* < 0 : errno that occurred
* 0 : no PIDs killed
* 1 : at least one PID killed
*/ */
int virCgroupKill(virCgroupPtr group, int signum) int virCgroupKill(virCgroupPtr group, int signum)
{ {
VIR_DEBUG("group=%p path=%s signum=%d", group, group->path, signum); VIR_DEBUG("group=%p path=%s signum=%d", group, group->path, signum);
int rc; int ret;
/* The 'tasks' file in cgroups can contain duplicated /* The 'tasks' file in cgroups can contain duplicated
* pids, so we use a hash to track which we've already * pids, so we use a hash to track which we've already
* killed. * killed.
@ -2457,37 +2462,42 @@ int virCgroupKill(virCgroupPtr group, int signum)
virCgroupPidCopy, virCgroupPidCopy,
NULL); NULL);
rc = virCgroupKillInternal(group, signum, pids); ret = virCgroupKillInternal(group, signum, pids);
virHashFree(pids); virHashFree(pids);
return rc; return ret;
} }
static int virCgroupKillRecursiveInternal(virCgroupPtr group, int signum, virHashTablePtr pids, bool dormdir) static int virCgroupKillRecursiveInternal(virCgroupPtr group, int signum, virHashTablePtr pids, bool dormdir)
{ {
int ret = -1;
int rc; int rc;
int killedAny = 0; bool killedAny = false;
char *keypath = NULL; char *keypath = NULL;
DIR *dp; DIR *dp;
virCgroupPtr subgroup = NULL; virCgroupPtr subgroup = NULL;
struct dirent *ent; struct dirent *ent;
VIR_DEBUG("group=%p path=%s signum=%d pids=%p", group, group->path, signum, pids); VIR_DEBUG("group=%p path=%s signum=%d pids=%p", group, group->path, signum, pids);
rc = virCgroupPathOfController(group, -1, "", &keypath); if (virCgroupPathOfController(group, -1, "", &keypath) < 0) {
if (rc != 0) { virReportError(VIR_ERR_INTERNAL_ERROR,
VIR_DEBUG("No path of %s, tasks", group->path); _("No tasks file for group path '%s'"),
return rc; group->path);
return -1;
} }
if ((rc = virCgroupKillInternal(group, signum, pids)) != 0) if ((rc = virCgroupKillInternal(group, signum, pids)) < 0)
return rc; return -1;
if (rc == 1)
killedAny = true;
VIR_DEBUG("Iterate over children of %s", keypath); VIR_DEBUG("Iterate over children of %s", keypath);
if (!(dp = opendir(keypath))) { if (!(dp = opendir(keypath))) {
rc = -errno; virReportSystemError(errno,
return rc; _("Cannot open %s"), keypath);
return -1;
} }
while ((ent = readdir(dp))) { while ((ent = readdir(dp))) {
@ -2500,16 +2510,13 @@ static int virCgroupKillRecursiveInternal(virCgroupPtr group, int signum, virHas
VIR_DEBUG("Process subdir %s", ent->d_name); VIR_DEBUG("Process subdir %s", ent->d_name);
if (virCgroupNew(ent->d_name, group, -1, &subgroup) < 0) { if (virCgroupNew(ent->d_name, group, -1, &subgroup) < 0)
virErrorSetErrnoFromLastError();
rc = -errno;
goto cleanup; goto cleanup;
}
if ((rc = virCgroupKillRecursiveInternal(subgroup, signum, pids, true)) < 0) if ((rc = virCgroupKillRecursiveInternal(subgroup, signum, pids, true)) < 0)
goto cleanup; goto cleanup;
if (rc == 1) if (rc == 1)
killedAny = 1; killedAny = true;
if (dormdir) if (dormdir)
virCgroupRemove(subgroup); virCgroupRemove(subgroup);
@ -2517,18 +2524,18 @@ static int virCgroupKillRecursiveInternal(virCgroupPtr group, int signum, virHas
virCgroupFree(&subgroup); virCgroupFree(&subgroup);
} }
rc = killedAny; ret = killedAny ? 1 : 0;
cleanup: cleanup:
virCgroupFree(&subgroup); virCgroupFree(&subgroup);
closedir(dp); closedir(dp);
return rc; return ret;
} }
int virCgroupKillRecursive(virCgroupPtr group, int signum) int virCgroupKillRecursive(virCgroupPtr group, int signum)
{ {
int rc; int ret;
VIR_DEBUG("group=%p path=%s signum=%d", group, group->path, signum); VIR_DEBUG("group=%p path=%s signum=%d", group, group->path, signum);
virHashTablePtr pids = virHashCreateFull(100, virHashTablePtr pids = virHashCreateFull(100,
NULL, NULL,
@ -2537,18 +2544,18 @@ int virCgroupKillRecursive(virCgroupPtr group, int signum)
virCgroupPidCopy, virCgroupPidCopy,
NULL); NULL);
rc = virCgroupKillRecursiveInternal(group, signum, pids, false); ret = virCgroupKillRecursiveInternal(group, signum, pids, false);
virHashFree(pids); virHashFree(pids);
return rc; return ret;
} }
int virCgroupKillPainfully(virCgroupPtr group) int virCgroupKillPainfully(virCgroupPtr group)
{ {
size_t i; size_t i;
int rc; int ret;
VIR_DEBUG("cgroup=%p path=%s", group, group->path); VIR_DEBUG("cgroup=%p path=%s", group, group->path);
for (i = 0; i < 15; i++) { for (i = 0; i < 15; i++) {
int signum; int signum;
@ -2559,33 +2566,39 @@ int virCgroupKillPainfully(virCgroupPtr group)
else else
signum = 0; /* Just check for existence */ signum = 0; /* Just check for existence */
rc = virCgroupKillRecursive(group, signum); ret = virCgroupKillRecursive(group, signum);
VIR_DEBUG("Iteration %zu rc=%d", i, rc); VIR_DEBUG("Iteration %zu rc=%d", i, ret);
/* If rc == -1 we hit error, if 0 we ran out of PIDs */ /* If ret == -1 we hit error, if 0 we ran out of PIDs */
if (rc <= 0) if (ret <= 0)
break; break;
usleep(200 * 1000); usleep(200 * 1000);
} }
VIR_DEBUG("Complete %d", rc); VIR_DEBUG("Complete %d", ret);
return rc; return ret;
} }
#else /* !(HAVE_KILL, HAVE_MNTENT_H, HAVE_GETMNTENT_R) */ #else /* !(HAVE_KILL, HAVE_MNTENT_H, HAVE_GETMNTENT_R) */
int virCgroupKill(virCgroupPtr group ATTRIBUTE_UNUSED, int virCgroupKill(virCgroupPtr group ATTRIBUTE_UNUSED,
int signum ATTRIBUTE_UNUSED) int signum ATTRIBUTE_UNUSED)
{ {
return -ENOSYS; virReportSystemError(ENOSYS, "%s",
_("Control groups not supported on this platform"));
return -1;
} }
int virCgroupKillRecursive(virCgroupPtr group ATTRIBUTE_UNUSED, int virCgroupKillRecursive(virCgroupPtr group ATTRIBUTE_UNUSED,
int signum ATTRIBUTE_UNUSED) int signum ATTRIBUTE_UNUSED)
{ {
return -ENOSYS; virReportSystemError(ENOSYS, "%s",
_("Control groups not supported on this platform"));
return -1;
} }
int virCgroupKillPainfully(virCgroupPtr group ATTRIBUTE_UNUSED) int virCgroupKillPainfully(virCgroupPtr group ATTRIBUTE_UNUSED)
{ {
return -ENOSYS; virReportSystemError(ENOSYS, "%s",
_("Control groups not supported on this platform"));
return -1;
} }
#endif /* HAVE_KILL, HAVE_MNTENT_H, HAVE_GETMNTENT_R */ #endif /* HAVE_KILL, HAVE_MNTENT_H, HAVE_GETMNTENT_R */