From: Oren Laadan <orenl-eQaUEPhvms7ENvBUuze7eA@public.gmane.org>
To: Dan Smith <danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Cc: containers-qjLDD68F18O7TbgM5vRIOg@public.gmane.org
Subject: Re: [PATCH] Add a multi-process IPC test
Date: Sat, 11 Apr 2009 20:42:38 -0400 [thread overview]
Message-ID: <49E138FE.5000805@cs.columbia.edu> (raw)
In-Reply-To: <1239299170-14827-1-git-send-email-danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Thanks, added to user-cr.git for next version.
Oren.
Dan Smith wrote:
> This test forks off several children in various states to ensure that the
> IPC namespace information is properly restored after restart.
>
> Cc: orenl-eQaUEPhvms7ENvBUuze7eA@public.gmane.org
> Signed-off-by: Dan Smith <danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
> ---
> Makefile | 2 +-
> tst_ipcshm_multi.c | 266 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 267 insertions(+), 1 deletions(-)
> create mode 100644 tst_ipcshm_multi.c
>
> diff --git a/Makefile b/Makefile
> index c847a0c..2da03bb 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -19,7 +19,7 @@ CFLAGS += -g $(WARNS) $(PATHS) $(DEBUG)
>
> PROGS = self ckpt rstr mktree
> TESTS= tst_onetask tst_multitask tst_bigmem tst_pipes tst_pipes2 tst_shmem \
> - tst_ipcshm tst_ipcmsq
> + tst_ipcshm tst_ipcmsq tst_ipcshm_multi
>
> LDLIBS = -lm
>
> diff --git a/tst_ipcshm_multi.c b/tst_ipcshm_multi.c
> new file mode 100644
> index 0000000..1ef31f7
> --- /dev/null
> +++ b/tst_ipcshm_multi.c
> @@ -0,0 +1,266 @@
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +#include <errno.h>
> +#include <sys/ipc.h>
> +#include <sys/shm.h>
> +
> +#include <linux/sched.h>
> +#include <sched.h>
> +
> +#define OUTFILE "/tmp/cr-test.out"
> +#define SEG_SIZE (20 * 4096)
> +#define DELAY 20
> +
> +int attach(unsigned char **seg, int num)
> +{
> + int id;
> +
> + id = shmget(123, SEG_SIZE, 0700|IPC_EXCL);
> + if (id < 0) {
> + printf("[CHILD %i] shmget: %m\n", num);
> + return -1;
> + }
> +
> + *seg = shmat(id, NULL, 0);
> + if (!*seg) {
> + printf("[CHILD %i] shmat: %m\n", num);
> + return -1;
> + }
> +
> + printf("[CHILD %i] Attached\n", num);
> +
> + return 0;
> +}
> +
> +int validate(unsigned char *seg, int num)
> +{
> + int i;
> +
> + for (i = 1; i < SEG_SIZE; i++) {
> + if (seg[i] != (unsigned char)(i % 256)) {
> + printf("[CHILD %i] Mismatch at %hhu: %hhu\n",
> + num, i, seg[i]);
> + return -1;
> + }
> + }
> +
> + printf("[CHILD %i] Validated\n", num);
> +
> + return 0;
> +}
> +
> +void track(unsigned char *seg, int num)
> +{
> + int i;
> +
> + for (i = 0; i < 20; i++) {
> + printf("[CHILD %i] Seg[0]: %i\n", num, seg[0]);
> + sleep(1);
> + }
> +}
> +
> +/*
> + * Attach to the shared segment *before* the checkpoint and then track
> + * the changing seg[0] position afterwards.
> + */
> +int child1(void)
> +{
> + unsigned char *seg;
> + int num = 1;
> +
> + printf("[CHILD %i] Running\n", num);
> +
> + sleep(1); /* Allow master to finish initializing the array */
> +
> + if (attach(&seg, num))
> + return -1;
> +
> + if (validate(seg, num))
> + return -1;
> +
> + sleep(DELAY - 1); /* Wait until after the checkpoint */
> +
> + track(seg, num);
> +
> + return 0;
> +}
> +
> +/*
> + * Attempt to attach to the shared segment *after* the checkpoint to
> + * verify that things are hooked up properly after restart by tracking
> + * seg[0].
> + */
> +int child2(void)
> +{
> + unsigned char *seg;
> + int num = 2;
> +
> + printf("[CHILD %i] Running\n", num);
> +
> + sleep(DELAY); /* Wait until after the checkpoint */
> +
> + if (attach(&seg, num))
> + return -1;
> +
> + if (validate(seg, num))
> + return -1;
> +
> + track(seg, num);
> +
> + return 0;
> +}
> +
> +int child4(void);
> +
> +/*
> + * Detach from the parent's IPC namespace and verify that:
> + * 1. We can't attach to the parent's segment
> + * 2. We can create our own of the same ID without conflict
> + * 3. We do not see the parent's changing seg[0] after restart
> + */
> +int child3(void)
> +{
> + unsigned char *seg;
> + int num = 3;
> +
> + if (unshare(CLONE_NEWIPC) != 0) {
> + printf("[CHILD %i] unshare(CLONE_NEWIPC): %m", num);
> + return -1;
> + }
> +
> + if (fork() == 0)
> + return child4();
> +
> + printf("[CHILD %i] Running (new IPC NS)\n", num);
> +
> + printf("[CHILD %i] Attempting parent attach (should fail)\n", num);
> + if (!attach(&seg, num)) {
> + printf("[CHILD %i] Attached to parent's IPC!\n", num);
> + return -1;
> + }
> +
> + if (shmget(123, SEG_SIZE, 0700|IPC_CREAT|IPC_EXCL) < 0) {
> + printf("[CHILD %i] Failed to create shm in namespace: %m\n",
> + num);
> + return -1;
> + }
> +
> + if (attach(&seg, num))
> + return -1;
> +
> + seg[0] = 123;
> +
> + sleep(DELAY); /* Wait until after checkpoint, then attach */
> +
> + track(seg, num);
> +
> + return 0;
> +}
> +
> +/*
> + * This child is forked from child3 under the new IPC namespace.
> + * Verify that post-restart, we do not see the changing seg[0]
> + */
> +int child4(void)
> +{
> + unsigned char *seg;
> + int num = 4;
> +
> + printf("[CHILD %i] Running (new IPC NS)\n", num);
> +
> + sleep(DELAY); /* Wait past my parent creating the IPC */
> +
> + if (attach(&seg, num))
> + return -1;
> +
> + track(seg, num);
> +
> + return 0;
> +}
> +
> +void shm_destroy(void)
> +{
> + int id;
> +
> + id = shmget(123, SEG_SIZE, 0700);
> + if (id < 0)
> + return;
> +
> + if (shmctl(id, IPC_RMID, NULL) == 0)
> + printf("Deleted SHM %i\n", id);
> +}
> +
> +int main(int argc, char *argv[])
> +{
> + int id;
> + unsigned char *seg;
> + int i;
> + int pid1, pid2, pid3;
> +#ifndef TEST
> + FILE *file;
> +
> + close(0);
> + close(1);
> + close(2);
> +
> + unlink(OUTFILE);
> + file = fopen(OUTFILE, "w+");
> + if (!file) {
> + perror("open");
> + exit(1);
> + }
> + if (dup2(0,2) < 0) {
> + perror("dup2");
> + exit(2);
> + }
> + stdout = file;
> + setlinebuf(file);
> +#endif
> + shm_destroy();
> +
> + pid1 = fork();
> + if (pid1 == 0)
> + return child1();
> +
> + pid2 = fork();
> + if (pid2 == 0)
> + return child2();
> +
> + pid3 = fork();
> + if (pid3 == 0)
> + return child3();
> +
> + id = shmget(123, SEG_SIZE, 0700|IPC_CREAT|IPC_EXCL);
> + if (id < 0) {
> + perror("shmget");
> + exit(1);
> + }
> +
> + seg = (unsigned char *) shmat(id, NULL, 0);
> + if(seg == ((void *) -1)) {
> + perror("shmat");
> + exit(1);
> + }
> +
> + for (i = 0; i < SEG_SIZE; i++)
> + seg[i] = i;
> +
> + printf("[MSTER] Waiting for checkpoint\n");
> + sleep(DELAY);
> + printf("[MSTER] Woke\n");
> +
> + for (i = 0; i < 15; i++) {
> + seg[0] = i;
> + sleep(1);
> + }
> +
> + if (shmdt(seg) < 0)
> + perror("shmdt");
> +
> + shm_destroy();
> +
> + printf("[MSTER] Completed\n");
> +
> + return 0;
> +}
prev parent reply other threads:[~2009-04-12 0:42 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-04-09 17:46 [PATCH] Add a multi-process IPC test Dan Smith
[not found] ` <1239299170-14827-1-git-send-email-danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2009-04-09 17:51 ` Dan Smith
2009-04-09 18:51 ` Serge E. Hallyn
[not found] ` <20090409185159.GA32610-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2009-04-09 18:58 ` Dan Smith
2009-04-11 23:48 ` Oren Laadan
[not found] ` <49E12C5F.5020209-eQaUEPhvms7ENvBUuze7eA@public.gmane.org>
2009-04-12 14:20 ` Serge E. Hallyn
2009-04-12 0:42 ` Oren Laadan [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=49E138FE.5000805@cs.columbia.edu \
--to=orenl-eqauephvms7envbuuze7ea@public.gmane.org \
--cc=containers-qjLDD68F18O7TbgM5vRIOg@public.gmane.org \
--cc=danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox