[LTP] [PATCH v2 03/13] hugeshmctl01: Convert to LTP synchronisation primitives
Cyril Hrubis
chrubis@suse.cz
Mon Nov 27 17:52:44 CET 2017
Hi!
> static void stat_setup(void);
> static void stat_cleanup(void);
> static void set_setup(void);
> @@ -141,19 +139,10 @@ void *set_shmat(void)
> */
> static void stat_setup(void)
> {
> - int i, rval;
> + int i;
> void *test;
> pid_t pid;
> - sigset_t newmask, oldmask;
> - struct sigaction sa;
> -
> - memset (&sa, '\0', sizeof(sa));
> - sa.sa_handler = sighandler;
> - sa.sa_flags = 0;
> - TEST(sigaction(SIGUSR1, &sa, NULL));
> - if (TEST_RETURN == -1)
> - tst_brk(TBROK | TRERRNO,
> - "SIGSEGV signal setup failed");
> +
> /*
> * The first time through, let the children attach the memory.
> * The second time through, attach the memory first and let
> @@ -168,21 +157,6 @@ static void stat_setup(void)
> set_shared = set_shmat();
> }
>
> - /*
> - * Block SIGUSR1 before children pause for a signal
> - * Doing so to avoid the risk that the parent cleans up
> - * children by calling stat_cleanup() before children call
> - * call pause() so that children sleep forever(this is a
> - * side effect of the arbitrary usleep time below).
> - * In FIRST, children call shmat. If children sleep forever,
> - * those attached shm can't be released so some other shm
> - * tests will fail a lot.
> - */
> - sigemptyset(&newmask);
> - sigaddset(&newmask, SIGUSR1);
> - if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
> - tst_brk(TBROK | TERRNO, "block SIGUSR1 error");
> -
> for (i = 0; i < N_ATTACH; i++) {
> switch (pid = SAFE_FORK()) {
> case 0:
> @@ -191,39 +165,24 @@ static void stat_setup(void)
> /* do an assignement for fun */
> *(int *)test = i;
>
> - /*
> - * sigsuspend until we get a signal from stat_cleanup()
> - * use sigsuspend instead of pause to avoid children
> - * infinite sleep without getting SIGUSR1 from parent
> - */
> - rval = sigsuspend(&oldmask);
> - if (rval != -1)
> - tst_brk(TBROK | TERRNO, "sigsuspend");
> -
> - /*
> - * don't have to block SIGUSR1 any more,
> - * recover the mask
> - */
> - if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
> - tst_brk(TBROK | TERRNO,
> - "child sigprocmask");
> + /* If last child then wake the parent */
> + if (i == N_ATTACH - 1)
> + TST_CHECKPOINT_WAKE(0);
As far as I can tell the assumption that the children are executed in
any order does not hold at all. So the parent should wait for _each_ of
them separately.
I guess that we have to suspend the parent process with
TST_CHECKPOINT_WAIT() after each fork() and wait till the children wakes
up the parent before we attempt to fork next child.
> + TST_CHECKPOINT_WAIT(1);
>
> /* now we're back - detach the memory and exit */
> if (shmdt(test) == -1)
> tst_brk(TBROK | TERRNO,
> "shmdt in stat_setup()");
> +
> + /* Child process quits here */
Please avoid adding obvious comments like this one. The original code is
not a good example and should be cleaned up.
> exit(0);
> - default:
> - /* save the child's pid for cleanup later */
> - pid_arr[i] = pid;
> }
> }
>
> - /* parent doesn't have to block SIGUSR1, recover the mask */
> - if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
> - tst_brk(TBROK, "parent sigprocmask");
> -
> - usleep(250000);
> + /* Wait for all the children to attach to shared memory */
> + TST_CHECKPOINT_WAIT(0);
> }
>
> /*
> @@ -283,11 +242,8 @@ fail:
> */
> static void stat_cleanup(void)
> {
> - int i;
> -
> /* wake up the childern so they can detach the memory and exit */
> - for (i = 0; i < N_ATTACH; i++)
> - SAFE_KILL(pid_arr[i], SIGUSR1);
> + TST_CHECKPOINT_WAKE2(1, N_ATTACH);
We should still SAFE_WAIT() each of the processses here otherwise we
cannot guarantee that the memory was detached and that the child really
exitted.
> /* remove the parent's shared memory the second time through */
> if (stat_time == SECOND)
> @@ -296,12 +252,6 @@ static void stat_cleanup(void)
> stat_time++;
> }
>
> -static void sighandler(int sig)
> -{
> - if (sig != SIGUSR1)
> - tst_res(TFAIL, "received unexpected signal %d", sig);
> -}
> -
> /*
> * set_setup() - set up for the IPC_SET command with shmctl()
> */
> @@ -387,4 +337,5 @@ static struct tst_test test = {
> .setup = setup,
> .cleanup = cleanup,
> .test_all = test_hugeshmctl,
> + .needs_checkpoints = 1,
> };
> --
> 2.14.2
>
--
Cyril Hrubis
chrubis@suse.cz
More information about the ltp
mailing list