From: <Nad...@bu...> - 2008-12-11 15:15:47
|
This testcase checks if the si_pid is correctly set when a process that has registered for notification on a posix mqueue is in a descendant namespace wrt the process that sends a message to that posix mqueue. Signed-off-by: Nadia Derbey <Nad...@bu...> --- testcases/kernel/containers/pidns/Makefile | 2 testcases/kernel/containers/pidns/pidns30.c | 331 ++++++++++++++++++++++ testcases/kernel/containers/pidns/runpidnstest.sh | 6 3 files changed, 338 insertions(+), 1 deletion(-) Index: ltp-full-20081130/testcases/kernel/containers/pidns/Makefile =================================================================== --- ltp-full-20081130.orig/testcases/kernel/containers/pidns/Makefile 2008-09-18 13:58:50.000000000 +0200 +++ ltp-full-20081130/testcases/kernel/containers/pidns/Makefile 2008-12-11 17:06:54.000000000 +0100 @@ -20,7 +20,7 @@ CFLAGS += -Wall CPPFLAGS += -I../../../../include -I../libclone -LDLIBS += -L../../../../lib -L../libclone ../libclone/libclone.a -lltp +LDLIBS += -L../../../../lib -L../libclone ../libclone/libclone.a -lltp -lrt SRCS := $(wildcard *.c) TARGETS := $(SRCS:%.c=%) Index: ltp-full-20081130/testcases/kernel/containers/pidns/pidns30.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ltp-full-20081130/testcases/kernel/containers/pidns/pidns30.c 2008-12-11 17:08:26.000000000 +0100 @@ -0,0 +1,331 @@ +/* +* Copyright (c) Bull S.A.S. 2008 +* 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 +* +*************************************************************************** +* File: pidns30.c +* +* Description: +* This testcase checks if the si_pid is correctly set when a process +* that has registered for notification on a posix mqueue is in a +* descendant namespace wrt the process that sends a message to that posix +* mqueue. +* +* Test Assertion & Strategy: +* Parent Child +* -------------------------------------------------------------------------- +* Create a POSIX mqueue. +* Create a PID namespace container. +* Open that mqueue for reading +* Register for notification when a +* message arrives in that mqueue +* Install a handler for SIGUSR1. +* Write something to the mqueue. +* Inside the handler, check that +* si_pid is set to 0 +* +* Usage: <for command-line> +* pidns30 +* +* History: +* DATE NAME DESCRIPTION +* 01/12/08 Nadia Derbey Creation of this test. +* <Nad...@bu...> +* +******************************************************************************/ +#define _GNU_SOURCE 1 +#include <sys/wait.h> +#include <sys/types.h> +#include <signal.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> +#include <mqueue.h> +#include <usctest.h> +#include <test.h> +#include <libclone.h> + +char *TCID = "pidns30"; +int TST_TOTAL = 1; + +char *mqname = "/mq1"; +int result = TFAIL; + +int errno; +int father_to_child[2]; +int child_to_father[2]; + +#define CHILD_PID 1 +#define PARENT_PID 0 + +#define MSG "HOW ARE YOU" +#define MSG_PRIO 1 + +/* + * cleanup() - performs all ONE TIME cleanup for this test at + * completion or premature exit. + */ +static void cleanup(int r) +{ + /* Clean the test testcase as LTP wants*/ + TEST_CLEANUP; + + /* exit with return code appropriate for results */ + tst_exit(r); +} + +/* + * child_signal_handler() - to handle SIGUSR1 + */ +static void child_signal_handler(int sig, siginfo_t *si, void *unused) +{ + char buf[256]; + mqd_t rc; + struct mq_attr attr; + + if (si->si_signo != SIGUSR1) { + tst_resm(TBROK, "cinit: received %s unexpectedly", + strsignal(si->si_signo)); + return; + } + + if (si->si_code != SI_MESGQ) { + tst_resm(TBROK, "cinit: expected signal code SI_MESGQ - Got %d", + si->si_code); + return; + } + + if (si->si_pid) { + tst_resm(TFAIL, + "cinit: expected signal originator PID = 0 - Got %d", + si->si_pid); + return; + } + + tst_resm(TPASS, "cinit: signal originator PID = 0"); + result = TPASS; + + /* + * Now read the message - Be silent on errors since this is not the + * test purpose. + */ + rc = mq_getattr((mqd_t)si->si_int, &attr); + if (rc == (mqd_t)-1) + return; + + mq_receive((mqd_t)si->si_int, buf, attr.mq_msgsize, NULL); +} + + +/* + * child_fn() - Inside container + */ +int child_fn(void *arg) +{ + pid_t pid, ppid; + struct sigaction sa; + mqd_t mqd; + struct sigevent notif; + char buf[5]; + + /* Set process id and parent pid */ + pid = getpid(); + ppid = getppid(); + + if (pid != CHILD_PID || ppid != PARENT_PID) { + tst_resm(TBROK, "cinit: pidns is not created"); + cleanup(TBROK); + } + + /* Close the appropriate end of each pipe */ + close(child_to_father[0]); + close(father_to_child[1]); + + mqd = mq_open(mqname, O_RDONLY); + if (mqd == (mqd_t)-1) { + tst_resm(TBROK, "cinit: mq_open() failed (%s)", + strerror(errno)); + cleanup(TBROK); + } + tst_resm(TINFO, "cinit: mq_open succeeded"); + + /* Register for notification on message arrival */ + notif.sigev_notify = SIGEV_SIGNAL; + notif.sigev_signo = SIGUSR1; + notif.sigev_value.sival_int = mqd; + if (mq_notify(mqd, ¬if) == (mqd_t)-1) { + tst_resm(TBROK, "cinit: mq_notify() failed (%s)", + strerror(errno)); + mq_close(mqd); + cleanup(TBROK); + } + tst_resm(TINFO, "cinit: successfully registered for notification"); + + /* Define handler for SIGUSR1 */ + sa.sa_flags = SA_SIGINFO; + sigemptyset(&sa.sa_mask); + sa.sa_sigaction = child_signal_handler; + if (sigaction(SIGUSR1, &sa, NULL) == -1) { + tst_resm(TBROK, "cinit: sigaction() failed(%s)", + strerror(errno)); + mq_notify(mqd, NULL); + mq_close(mqd); + cleanup(TBROK); + } + tst_resm(TINFO, "cinit: successfully registered handler for SIGUSR1"); + + /* Ask parent to send a message to the mqueue */ + if (write(child_to_father[1], "c:ok", 5) != 5) { + tst_resm(TBROK, "cinit: pipe is broken (%s)", strerror(errno)); + mq_notify(mqd, NULL); + mq_close(mqd); + cleanup(TBROK); + } + + sleep(3); + + /* Has parent sent a message? */ + read(father_to_child[0], buf, 5); + if (strcmp(buf, "f:ok")) { + tst_resm(TBROK, "cinit: parent did not send the message!"); + mq_notify(mqd, NULL); + mq_close(mqd); + cleanup(TBROK); + } + tst_resm(TINFO, "cinit: my father is done - cleaning"); + + /* Be silent on errors from now on */ + mq_close(mqd); + + /* Cleanup and exit */ + close(child_to_father[1]); + close(father_to_child[0]); + exit(0); +} + +static void remove_pipe(int *fd) +{ + close(fd[0]); + close(fd[1]); +} + +/*********************************************************************** +* M A I N +***********************************************************************/ + +int main(int argc, char *argv[]) +{ + int stack_size = getpagesize() * 4; + void *stack = malloc(stack_size); + void *childstack; + int status; + char buf[5]; + pid_t cpid; + mqd_t mqd; + mqd_t rc; + + if (!stack) { + tst_resm(TBROK, "parent: stack creation failed."); + cleanup(TBROK); + } + + if (pipe(child_to_father) == -1) { + tst_resm(TBROK, "parent: pipe() failed. aborting!"); + cleanup(TBROK); + } + + if (pipe(father_to_child) == -1) { + tst_resm(TBROK, "parent: pipe() failed. aborting!"); + remove_pipe(child_to_father); + cleanup(TBROK); + } + + mq_unlink(mqname); + mqd = mq_open(mqname, O_RDWR|O_CREAT|O_EXCL, 0777, NULL); + if (mqd == (mqd_t)-1) { + tst_resm(TBROK, "parent: mq_open() failed (%s)", + strerror(errno)); + remove_pipe(father_to_child); + remove_pipe(child_to_father); + cleanup(TBROK); + } + tst_resm(TINFO, "parent: successfully created posix mqueue"); + + /* container creation on PID namespace */ + childstack = stack + stack_size; + cpid = clone(child_fn, childstack, CLONE_NEWPID|SIGCHLD, NULL); + if (cpid < 0) { + tst_resm(TBROK, "parent: clone() failed(%s)", strerror(errno)); + mq_close(mqd); + mq_unlink(mqname); + remove_pipe(father_to_child); + remove_pipe(child_to_father); + cleanup(TBROK); + } + + /* Close the appropriate end of each pipe */ + close(child_to_father[1]); + close(father_to_child[0]); + + /* Is container ready */ + read(child_to_father[0], buf, 5); + if (strcmp(buf, "c:ok")) { + tst_resm(TBROK, "parent: container did not respond!"); + mq_close(mqd); + mq_unlink(mqname); + remove_pipe(father_to_child); + remove_pipe(child_to_father); + cleanup(TBROK); + } + + rc = mq_send(mqd, MSG, strlen(MSG), MSG_PRIO); + if (rc == (mqd_t)-1) { + tst_resm(TBROK, "parent: mq_send() failed (%s)", + strerror(errno)); + mq_close(mqd); + mq_unlink(mqname); + remove_pipe(father_to_child); + remove_pipe(child_to_father); + cleanup(TBROK); + } + tst_resm(TINFO, "parent: mq_send() succeeded"); + + /* Tell the child the message has been sent */ + if (write(father_to_child[1], "f:ok", 5) != 5) { + tst_resm(TBROK, "father: pipe is broken(%s)", strerror(errno)); + mq_close(mqd); + mq_unlink(mqname); + remove_pipe(father_to_child); + remove_pipe(child_to_father); + cleanup(TBROK); + } + + /* Wait for child to finish */ + if (wait(&status) == -1) { + tst_resm(TBROK, "parent: wait() failed(%s)", strerror(errno)); + mq_close(mqd); + mq_unlink(mqname); + remove_pipe(father_to_child); + remove_pipe(child_to_father); + cleanup(TBROK); + } + + mq_close(mqd); + mq_unlink(mqname); + close(child_to_father[0]); + close(father_to_child[1]); + cleanup(result); + + /* NOT REACHED */ + return 0; +} /* End main */ Index: ltp-full-20081130/testcases/kernel/containers/pidns/runpidnstest.sh =================================================================== --- ltp-full-20081130.orig/testcases/kernel/containers/pidns/runpidnstest.sh 2008-11-18 10:11:23.000000000 +0100 +++ ltp-full-20081130/testcases/kernel/containers/pidns/runpidnstest.sh 2008-12-11 17:13:58.000000000 +0100 @@ -55,6 +55,12 @@ if [ $rc -ne 0 ] && [ -z $err_code ]; th err_code=$rc fi +pidns30 +rc=$? +if [ $rc -ne 0 ] && [ -z $err_code ]; then + err_code=$rc +fi + # If any test failed then exit with the value error-code. if ! [ -z $err_code ]; then exit $err_code -- |