From: <su...@li...> - 2008-11-03 19:35:22
|
Veerendra [ve...@li...] wrote: > Hi > > Please find the testcase for the below assertion. > <begin> > Assertions 1: > Steps: > a) Create a container . > b) Create many levels of child containers inside this container. > c) Now do kill -9 init , outside of the contaier. > d) This should kill all the child containers . (containers created at > the level below ) <end> This information could be in the patch description below. The rest could be just in the email and stripped out from patch. > > In this testcase , I am creating containers upto 5 levels. And I am > killing the container created at level 3. > And verifying that the containers created at level 4 and level 5 are > destroyed. > > Regards > Veerendra C | Results: | [root@temp1 pidns]# ./pidns05 | pidns05 0 INFO : 5 Nested Containers are created | pidns05 1 PASS : The number of containers killed are 2 | | Signed-off-by: Veerendra C <vec...@in...> Have a minor optimization below, but otherwise, Acked-by: Sukadev Bhattiprolu <su...@li...> | | Index: root/new/ltp-full-20080930/testcases/kernel/containers/pidns/pidns05.c | =================================================================== | --- /dev/null | +++ root/new/ltp-full-20080930/testcases/kernel/containers/pidns/pidns05.c | @@ -0,0 +1,264 @@ | +/* | +* Copyright (c) International Business Machines Corp., 2007 | +* This program is free software; you can redistribute it and/or modify | +* it under the terms of the GNU General Public License as published by | +* the Free Software Foundation; either version 2 of the License, or | +* (at your option) any later version. | +* This program is distributed in the hope that it will be useful | +* but WITHOUT ANY WARRANTY; without even the implied warranty of | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | +* the GNU General Public License for more details. | +* You should have received a copy of the GNU General Public License | +* along with this program; if not, write to the Free Software | +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | +* | +*************************************************************************** | +* | +* Description: | +* This testcase creates 5 nested containers. | +* And it will destroy a container, and verifies that the child | +* containers are also destroyed when the parent container is killed. | +* | +* 1. Parent process clone a process with flag CLONE_NEWPID | +* 2. The container will recursively loop and creates 4 more containers. | +* 3. All the container init's goes into sleep(), waiting to be terminated. | +* 4. The parent process will kill child[3] by passing SIGKILL | +* 5. Now parent process, verifies the child containers 4 & 5 are destroyed. | +* 6. If they are killed then | +* Test PASSed | +* else Test FAILed. | +* | +* Test Name: pidns05 | +* | +* History: | +* | +* FLAG DATE NAME DESCRIPTION | +* 31/10/08 Veerendra C <vec...@in...> Verifies killing of NestedCont's | +* | +*******************************************************************************/ | +#define _GNU_SOURCE 1 | +#include <sys/wait.h> | +#include <assert.h> | +#include <stdio.h> | +#include <stdlib.h> | +#include <unistd.h> | +#include <string.h> | +#include <errno.h> | +#include <usctest.h> | +#include <test.h> | +#include <libclone.h> | + | +#define INIT_PID 1 | +#define CINIT_PID 1 | +#define PARENT_PID 0 | +#define MAX_DEPTH 5 | + | +char *TCID = "pidns05"; | +int TST_TOTAL = 1; | +int fd[2]; | + | +void cleanup(void); | +int create_nested_container(void *); | + | +int max_pid() | +{ | + FILE *fp; | + int ret; | + | + fp = fopen("/proc/sys/kernel/pid_max", "r") ; | + if (fp != NULL) { | + fscanf(fp, "%d", &ret); | + fclose(fp); | + } else { | + tst_resm(TBROK, "Cannot open /proc/sys/kernel/pid_max \n"); | + ret = -1; | + } | + return ret; | +} | + | +/* find_cinit_pids() goes through the procfs for each of the pid, | + * and checks if it matches the 'name' and 'PGID' of the parent | + * process that created the containers. | + * Input : Accepts an integer array pids[], which stores the pid's matching | + * Returns count of the pids matched. | +*/ | +int find_cinit_pids(pid_t *pids) | +{ | + int ret, next = 0, pid, pid_max, i, tmp1, tmp3; | + pid_t parentpid, pgid; | + FILE *fp; | + char progname[FILENAME_MAX+2]; | + char proc_file[FILENAME_MAX]; | + char tmp2; | + | + pid_max = max_pid(); | + parentpid = getpid(); | + pgid = getpgid(parentpid); | + | + /* To wrap around if the pid has reached the max_pid */ | + if (parentpid != pid_max) | + i = parentpid + 1; | + else | + i = 2; Rather than checking against pid_max twice, you could simplify: for (i = parent_pid + 1; i != parent_pid; i++) { if (i >= pid_max) { i = 1; continue; } sprintf(proc_file, ...); } | + | + /* The loop breaks, when the loop counter reaches the parentpid value */ | + while (i != parentpid) { | + sprintf(proc_file, "/proc/%d/stat", i); | + fp = fopen(proc_file, "r"); | + | + /* The name and the PGID for each of the process should match* | + * the 'pidns05' and parent groupid for the parent process */ | + if (fp != NULL) { | + fscanf(fp, "%d %s %c %d %d", &tmp1, progname, &tmp2, | + &tmp3, &pid); | + ret = strcmp("(pidns05)", progname); | + if (ret == 0 && pid == pgid) { | + pids[next] = i; | + next++; | + } | + fclose(fp); | + } | + if (i == pid_max) | + i = 2; | + else | + i++; | + } | + return next; | +} | + | +/* | +* create_nested_container() Recursively create MAX_DEPTH nested containers | +*/ | +int create_nested_container(void *vtest) | +{ | + int ret, count, *level ; | + pid_t cpid, ppid; | + cpid = getpid(); | + ppid = getppid(); | + char mesg[] = "Nested Containers are created"; | + | + level = (int *)vtest; | + count = *level; | + | + /* Child process closes up read side of pipe */ | + close(fd[0]); | + | + /* Comparing the values to make sure pidns is created correctly */ | + if ((cpid != CINIT_PID) || (ppid != PARENT_PID)) { | + tst_resm(TFAIL, "FAIL: Got unexpected result of" | + " cpid=%d ppid=%d\n", cpid, ppid); | + cleanup(); | + } | + if (count > 1) { | + count--; | + ret = do_clone_unshare_test(T_CLONE, CLONE_NEWPID, | + create_nested_container, (void *) &count); | + if (ret == -1) { | + tst_resm(TFAIL, "clone() Failed, errno = %d : %s\n" , | + ret, strerror(ret)); | + cleanup(); | + } | + } else { | + /* Sending mesg, 'Nested containers created' through the pipe */ | + write(fd[1], mesg, (strlen(mesg)+1)); | + } | + | + close(fd[1]); | + pause(); | + | + /* NOT REACHED */ | + return 0; | +} | + | +/* | + * cleanup() - performs all ONE TIME cleanup for this test at | + * completion or premature exit. | + */ | +void cleanup() | +{ | + /* Clean the test testcase as LTP wants*/ | + TEST_CLEANUP; | + | + /* exit with return code appropriate for results */ | + tst_exit(); | +} | + | +void kill_nested_containers() | +{ | + int orig_count, new_count, status = 0, i; | + pid_t pids[MAX_DEPTH]; | + pid_t pids_new[MAX_DEPTH]; | + | + orig_count = find_cinit_pids(pids); | + kill(pids[MAX_DEPTH - 3], SIGKILL) ; | + sleep(1); | + | + /* After killing child container, getting the New PID list */ | + new_count = find_cinit_pids(pids_new); | + | + /*Verifyng if the child containers are destroyed when parent is killed*/ | + if (orig_count - 2 != new_count) | + status = -1; | + | + for (i = 0; i < new_count; i++) { | + if (pids[i] != pids_new[i]) | + status = -1; | + } | + | + if (status == 0) | + tst_resm(TPASS, "The number of containers killed are %d\n" , | + orig_count - new_count); | + else | + tst_resm(TFAIL, "Failed to kill the sub-containers of " | + "the container %d\n", pids[MAX_DEPTH - 3]); | + | + /* Loops through the containers created, to exit from sleep() */ | + for (i = 0; i < MAX_DEPTH; i++) { | + kill(pids[i], SIGKILL); | + waitpid(pids[i], &status, 0); | + } | +} | + | + | +/*********************************************************************** | +* M A I N | +***********************************************************************/ | + | +int main(int argc, char *argv[]) | +{ | + int ret, nbytes; | + char readbuffer[80]; | + int count = MAX_DEPTH; | + | + ret = pipe(fd); | + if (ret == -1) | + tst_brkm(TBROK, cleanup, "pipe() failed, errno %d", errno); | + | + ret = do_clone_unshare_test(T_CLONE, CLONE_NEWPID, | + create_nested_container, (void *) &count); | + if (ret == -1) { | + tst_resm(TFAIL, "clone() Failed, errno = %d : %s\n" , | + ret, strerror(ret)); | + cleanup(); | + } | + | + close(fd[1]); | + /* Waiting for the MAX_DEPTH number of containers to be created */ | + nbytes = read(fd[0], readbuffer, sizeof(readbuffer)); | + close(fd[0]); | + if (nbytes > 0) | + tst_resm(TINFO, " %d %s", MAX_DEPTH, readbuffer); | + else { | + tst_resm(TFAIL, "Unable to create %d containers\n", MAX_DEPTH); | + cleanup(); | + } | + | + /* Kill the container created */ | + kill_nested_containers(); | + /* cleanup and exit */ | + cleanup(); | + | + /*NOTREACHED*/ | + return 0; | +} | + |