/* * Kill the given cgroup and wait for the inotify signal. * If there are no events in 10 seconds, treat this as an error. * Then check that the cgroup is in the desired state.
*/ staticint cg_kill_wait(constchar *cgroup)
{ int fd, ret = -1;
fd = cg_prepare_for_wait(cgroup); if (fd < 0) return fd;
ret = cg_write(cgroup, "cgroup.kill", "1"); if (ret) goto out;
ret = cg_wait_for(fd); if (ret) goto out;
out:
close(fd); return ret;
}
/* * A simple process running in a sleep loop until being * re-parented.
*/ staticint child_fn(constchar *cgroup, void *arg)
{ int ppid = getppid();
while (getppid() == ppid)
usleep(1000);
return getppid() == ppid;
}
staticint test_cgkill_simple(constchar *root)
{
pid_t pids[100]; int ret = KSFT_FAIL; char *cgroup = NULL; int i;
cgroup = cg_name(root, "cg_test_simple"); if (!cgroup) goto cleanup;
if (cg_create(cgroup)) goto cleanup;
for (i = 0; i < 100; i++)
pids[i] = cg_run_nowait(cgroup, child_fn, NULL);
if (cg_wait_for_proc_count(cgroup, 100)) goto cleanup;
if (cg_read_strcmp(cgroup, "cgroup.events", "populated 1\n")) goto cleanup;
if (cg_kill_wait(cgroup)) goto cleanup;
ret = KSFT_PASS;
cleanup: for (i = 0; i < 100; i++)
wait_for_pid(pids[i]);
if (ret == KSFT_PASS &&
cg_read_strcmp(cgroup, "cgroup.events", "populated 0\n"))
ret = KSFT_FAIL;
if (cgroup)
cg_destroy(cgroup);
free(cgroup); return ret;
}
/* * The test creates the following hierarchy: * A * / / \ \ * B E I K * /\ | * C D F * | * G * | * H * * with a process in C, H and 3 processes in K. * Then it tries to kill the whole tree.
*/ staticint test_cgkill_tree(constchar *root)
{
pid_t pids[5]; char *cgroup[10] = {0}; int ret = KSFT_FAIL; int i;
cgroup[0] = cg_name(root, "cg_test_tree_A"); if (!cgroup[0]) goto cleanup;
cgroup[1] = cg_name(cgroup[0], "B"); if (!cgroup[1]) goto cleanup;
cgroup[2] = cg_name(cgroup[1], "C"); if (!cgroup[2]) goto cleanup;
cgroup[3] = cg_name(cgroup[1], "D"); if (!cgroup[3]) goto cleanup;
cgroup[4] = cg_name(cgroup[0], "E"); if (!cgroup[4]) goto cleanup;
cgroup[5] = cg_name(cgroup[4], "F"); if (!cgroup[5]) goto cleanup;
cgroup[6] = cg_name(cgroup[5], "G"); if (!cgroup[6]) goto cleanup;
cgroup[7] = cg_name(cgroup[6], "H"); if (!cgroup[7]) goto cleanup;
cgroup[8] = cg_name(cgroup[0], "I"); if (!cgroup[8]) goto cleanup;
cgroup[9] = cg_name(cgroup[0], "K"); if (!cgroup[9]) goto cleanup;
for (i = 0; i < 10; i++) if (cg_create(cgroup[i])) goto cleanup;
/* * Kill A and check that we get an empty notification.
*/ if (cg_kill_wait(cgroup[0])) goto cleanup;
ret = KSFT_PASS;
cleanup: for (i = 0; i < 5; i++)
wait_for_pid(pids[i]);
if (ret == KSFT_PASS &&
cg_read_strcmp(cgroup[0], "cgroup.events", "populated 0\n"))
ret = KSFT_FAIL;
for (i = 9; i >= 0 && cgroup[i]; i--) {
cg_destroy(cgroup[i]);
free(cgroup[i]);
}
return ret;
}
staticint forkbomb_fn(constchar *cgroup, void *arg)
{ int ppid;
fork();
fork();
ppid = getppid();
while (getppid() == ppid)
usleep(1000);
return getppid() == ppid;
}
/* * The test runs a fork bomb in a cgroup and tries to kill it.
*/ staticint test_cgkill_forkbomb(constchar *root)
{ int ret = KSFT_FAIL; char *cgroup = NULL;
pid_t pid = -ESRCH;
cgroup = cg_name(root, "cg_forkbomb_test"); if (!cgroup) goto cleanup;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.