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 <[EMAIL PROTECTED]>
---
 testcases/kernel/containers/pidns/Makefile  |    4 
 testcases/kernel/containers/pidns/pidns04.c |  331 ++++++++++++++++++++++++++++
 2 files changed, 333 insertions(+), 2 deletions(-)

Index: ltp-full-20080831/testcases/kernel/containers/pidns/Makefile
===================================================================
--- ltp-full-20080831.orig/testcases/kernel/containers/pidns/Makefile   
2008-08-31 16:33:01.000000000 +0200
+++ ltp-full-20080831/testcases/kernel/containers/pidns/Makefile        
2008-12-04 13:44:31.000000000 +0100
@@ -20,10 +20,10 @@
 
 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)
-NOLTPSRCS = pidns01.c pidns02.c pidns03.c
+NOLTPSRCS = pidns01.c pidns02.c pidns03.c pidns04.c
 TARGETS = $(patsubst %.c,%,$(SRCS))
 NOLTP_TARGETS = $(patsubst %.c,%_noltp,$(NOLTPSRCS))
 
Index: ltp-full-20080831/testcases/kernel/containers/pidns/pidns04.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ ltp-full-20080831/testcases/kernel/containers/pidns/pidns04.c       
2008-12-04 13:44:04.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: pidns04.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>
+*    pidns04
+*
+*   History:
+*    DATE      NAME                             DESCRIPTION
+*    01/12/08  Nadia Derbey               Creation of this test.
+*              <[EMAIL PROTECTED]>
+*
+******************************************************************************/
+#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 = "pidns04";
+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, &notif) == (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 */

-- 

------------------------------------------------------------------------------
SF.Net email is Sponsored by MIX09, March 18-20, 2009 in Las Vegas, Nevada.
The future of the web can't happen without you.  Join us at MIX09 to help
pave the way to the Next Web now. Learn more and register at
http://ad.doubleclick.net/clk;208669438;13503038;i?http://2009.visitmix.com/
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list

Reply via email to