From: <Nad...@bu...> - 2008-12-05 07:40:43
|
This testcase checks if the si_pid is correctly set when a process that has registered for notification on a posix mqueue is in an ancestor 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/pidns05.c | 304 ++++++++++++++++++++++++++++ 2 files changed, 305 insertions(+), 1 deletion(-) Index: ltp-full-20080831/testcases/kernel/containers/pidns/pidns05.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ltp-full-20080831/testcases/kernel/containers/pidns/pidns05.c 2008-12-04 17:38:15.000000000 +0100 @@ -0,0 +1,304 @@ +/* +* 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: pidns05.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 an +* ancestor 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. +* Register for notification when a +* message arrives in that mqueue +* Install a handler for SIGUSR1. +* Open that mqueue for writing +* Write something to the mqueue. +* Inside the handler, check that +* si_pid is set to the child's pid +* +* Usage: <for command-line> +* pidns05 +* +* History: +* DATE NAME DESCRIPTION +* 04/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 = "pidns05"; +int TST_TOTAL = 1; + +char *mqname = "/mq1"; +int result = TFAIL; + +int errno; +int father_to_child[2]; + +#define CHILD_PID 1 +#define PARENT_PID 0 + +#define MSG "HOW ARE YOU" +#define MSG_PRIO 1 + +struct notify_info { + mqd_t mqd; + pid_t pid; +}; + +/* + * 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_fn() - Inside container + */ +int child_fn(void *arg) +{ + pid_t pid, ppid; + mqd_t mqd; + 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 pipe */ + close(father_to_child[1]); + + /* Is parent ready to receive a message? */ + read(father_to_child[0], buf, 5); + if (strcmp(buf, "f:ok")) { + tst_resm(TBROK, "cinit: parent did not send the message!"); + cleanup(TBROK); + } + tst_resm(TINFO, "cinit: my father is ready to receive a message"); + + mqd = mq_open(mqname, O_WRONLY); + if (mqd == (mqd_t)-1) { + tst_resm(TBROK, "cinit: mq_open() failed (%s)", + strerror(errno)); + cleanup(TBROK); + } + tst_resm(TINFO, "cinit: mq_open succeeded"); + + if (mq_send(mqd, MSG, strlen(MSG), MSG_PRIO) == (mqd_t)-1) { + tst_resm(TBROK, "cinit: mq_send() failed (%s)", + strerror(errno)); + mq_close(mqd); + cleanup(TBROK); + } + tst_resm(TINFO, "cinit: mq_send() succeeded"); + + /* Cleanup and exit */ + mq_close(mqd); + close(father_to_child[0]); + exit(0); +} + +static void remove_pipe(int *fd) +{ + close(fd[0]); + close(fd[1]); +} + +/* + * father_signal_handler() + */ +static void father_signal_handler(int sig, siginfo_t *si, void *unused) +{ + char buf[256]; + struct mq_attr attr; + struct notify_info *info; + + if (si->si_signo != SIGUSR1) { + tst_resm(TBROK, "father: received %s unexpectedly", + strsignal(si->si_signo)); + return; + } + + if (si->si_code != SI_MESGQ) { + tst_resm(TBROK, "father: expected signal code SI_MESGQ - " + "Got %d", si->si_code); + return; + } + + if (!si->si_ptr) { + tst_resm(TBROK, "father: expected si_ptr - Got NULL"); + return; + } + + info = (struct notify_info *)si->si_ptr; + + if (si->si_pid != info->pid) { + tst_resm(TFAIL, + "father: expected signal originator PID = %d - Got %d", + info->pid, si->si_pid); + return; + } + + tst_resm(TPASS, "father: signal originator PID = %d", si->si_pid); + result = TPASS; + + /* + * Now read the message - Be silent on errors since this is not the + * test purpose. + */ + if (!mq_getattr(info->mqd, &attr)) + mq_receive(info->mqd, buf, attr.mq_msgsize, NULL); +} + +/*********************************************************************** +* M A I N +***********************************************************************/ + +int main(int argc, char *argv[]) +{ + int stack_size = getpagesize() * 4; + void *stack = malloc(stack_size); + void *childstack; + pid_t cpid; + mqd_t mqd; + struct sigevent notif; + struct sigaction sa; + int status; + struct notify_info info; + + if (!stack) { + tst_resm(TBROK, "parent: stack creation failed."); + cleanup(TBROK); + } + + if (pipe(father_to_child) == -1) { + tst_resm(TBROK, "parent: pipe() failed. aborting!"); + 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); + 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); + cleanup(TBROK); + } + tst_resm(TINFO, "parent: successfully created child (pid = %d)", cpid); + + /* Register for notification on message arrival */ + notif.sigev_notify = SIGEV_SIGNAL; + notif.sigev_signo = SIGUSR1; + info.mqd = mqd; + info.pid = cpid; + notif.sigev_value.sival_ptr = &info; + if (mq_notify(mqd, ¬if) == (mqd_t)-1) { + tst_resm(TBROK, "parent: mq_notify() failed (%s)", + strerror(errno)); + mq_close(mqd); + mq_unlink(mqname); + remove_pipe(father_to_child); + cleanup(TBROK); + } + tst_resm(TINFO, "parent: successfully registered for notification"); + + /* Define handler for SIGUSR1 */ + sa.sa_flags = SA_SIGINFO; + sigemptyset(&sa.sa_mask); + sa.sa_sigaction = father_signal_handler; + if (sigaction(SIGUSR1, &sa, NULL) == -1) { + tst_resm(TBROK, "parent: sigaction() failed(%s)", + strerror(errno)); + mq_notify(mqd, NULL); + mq_close(mqd); + mq_unlink(mqname); + remove_pipe(father_to_child); + cleanup(TBROK); + } + tst_resm(TINFO, "parent: successfully registered handler for SIGUSR1"); + + /* Close the appropriate end of pipe */ + close(father_to_child[0]); + + /* Tell the child a message can be sent */ + if (write(father_to_child[1], "f:ok", 5) != 5) { + tst_resm(TBROK, "parent: pipe is broken(%s)", strerror(errno)); + mq_notify(mqd, NULL); + mq_close(mqd); + mq_unlink(mqname); + remove_pipe(father_to_child); + cleanup(TBROK); + } + + sleep(3); + + /* 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); + cleanup(TBROK); + } + + mq_close(mqd); + mq_unlink(mqname); + close(father_to_child[1]); + cleanup(result); + + /* NOT REACHED */ + return 0; +} /* End main */ Index: ltp-full-20080831/testcases/kernel/containers/pidns/Makefile =================================================================== --- ltp-full-20080831.orig/testcases/kernel/containers/pidns/Makefile 2008-12-04 13:44:31.000000000 +0100 +++ ltp-full-20080831/testcases/kernel/containers/pidns/Makefile 2008-12-04 16:23:33.000000000 +0100 @@ -23,7 +23,7 @@ CPPFLAGS += -I../../../../include -I../l LDLIBS += -L../../../../lib -L../libclone ../libclone/libclone.a -lltp -lrt SRCS = $(wildcard *.c) -NOLTPSRCS = pidns01.c pidns02.c pidns03.c pidns04.c +NOLTPSRCS = pidns01.c pidns02.c pidns03.c pidns04.c pidns05.c TARGETS = $(patsubst %.c,%,$(SRCS)) NOLTP_TARGETS = $(patsubst %.c,%_noltp,$(NOLTPSRCS)) -- |