/* * stat_setup() - Set up for the IPC_STAT command with shmctl(). * Make things interesting by forking some children * that will either attach or inherit the shared memory. */ void stat_setup() { int i, rval; void *test, *set_shmat(); pid_t pid; /* * The first time through, let the children attach the memory. * The second time through, attach the memory first and let * the children inherit the memory. */ if (stat_time == SECOND) { /* * use the global "set_shared" variable here so that * it can be removed in the stat_func() routine. */ set_shared = set_shmat(); } for (i=0; i<N_ATTACH; i++) { if ((pid = fork()) == -1) { tst_brkm(TBROK, cleanup, "could not fork"); } if (pid == 0) { /* child */ if (stat_time == FIRST) { test = set_shmat(); } else { test = set_shared; } /* do an assignement for fun */ *(int *)test = i; /* pause until we get a signal from stat_cleanup() */ rval = pause(); /* now we're back - detach the memory and exit */ if (shmdt(test) == -1) { tst_resm(TBROK, "shmdt() failed - %d", errno); } tst_exit(); } else { /* parent */ /* save the child's pid for cleanup later */ pid_arr[i] = pid; } } /* sleep briefly to ensure correct execution order */ usleep(250000); }
/* * stat_setup() - Set up for the IPC_STAT command with shmctl(). * Make things interesting by forking some children * that will either attach or inherit the shared memory. */ void stat_setup() { void *set_shmat(); pid_t pid; /* * The first time through, let the children attach the memory. * The second time through, attach the memory first and let * the children inherit the memory. */ if (stat_time == SECOND) { /* * use the global "set_shared" variable here so that * it can be removed in the stat_func() routine. */ set_shared = set_shmat(); } tst_flush(); for (stat_i = 0; stat_i < N_ATTACH; stat_i++) { if (sync_pipe_create(sync_pipes, PIPE_NAME) == -1) tst_brkm(TBROK, cleanup, "sync_pipe_create failed"); if ((pid = FORK_OR_VFORK()) == -1) { tst_brkm(TBROK, cleanup, "could not fork"); } if (pid == 0) { /* child */ #ifdef UCLINUX if (self_exec(argv0, "ddd", stat_i, stat_time, shm_id_1) < 0) { tst_brkm(TBROK, cleanup, "could not self_exec"); } #else do_child(); #endif } else { /* parent */ /* save the child's pid for cleanup later */ pid_arr[stat_i] = pid; if (sync_pipe_wait(sync_pipes) == -1) tst_brkm(TBROK, cleanup, "sync_pipe_wait failed"); if (sync_pipe_close(sync_pipes, PIPE_NAME) == -1) tst_brkm(TBROK, cleanup, "sync_pipe_close failed"); } } /* Wait 1 second to be sure all sons are in the pause function. */ sleep(1); }
void do_child(void) { void *test; if (stat_time == FIRST) test = set_shmat(); else test = set_shared; memcpy(test, &stat_i, sizeof(stat_i)); /* pause until we get a signal from stat_cleanup() */ pause(); /* now we're back - detach the memory and exit */ if (shmdt(test) == -1) tst_resm(TBROK, "shmdt() failed - %d", errno); tst_exit(); }
/* * stat_setup() - Set up for the IPC_STAT command with shmctl(). * Make things interesting by forking some children * that will either attach or inherit the shared memory. */ void stat_setup(void) { void *set_shmat(); pid_t pid; /* * The first time through, let the children attach the memory. * The second time through, attach the memory first and let * the children inherit the memory. */ if (stat_time == SECOND) /* * use the global "set_shared" variable here so that * it can be removed in the stat_func() routine. */ set_shared = set_shmat(); tst_flush(); for (stat_i = 0; stat_i < N_ATTACH; stat_i++) { pid = FORK_OR_VFORK(); if (pid == -1) tst_brkm(TBROK, cleanup, "could not fork"); if (pid == 0) { #ifdef UCLINUX if (self_exec(argv0, "ddd", stat_i, stat_time, shm_id_1) < 0) tst_brkm(TBROK, cleanup, "could not self_exec"); #else do_child(); #endif } else { /* save the child's pid for cleanup later */ pid_arr[stat_i] = pid; TST_PROCESS_STATE_WAIT(cleanup, pid, 'S'); } } }
/* * do_child */ void do_child() { int rval; void *test; #ifdef UCLINUX if (sync_pipe_create(sync_pipes, PIPE_NAME) == -1) tst_brkm(TBROK, cleanup, "sync_pipe_create failed"); #endif if (stat_time == FIRST) { test = set_shmat(); } else { test = set_shared; } if (sync_pipe_notify(sync_pipes) == -1) tst_brkm(TBROK, cleanup, "sync_pipe_notify failed"); #ifdef UCLINUX if (sync_pipe_close(sync_pipes, NULL) == -1) #else if (sync_pipe_close(sync_pipes, PIPE_NAME) == -1) #endif tst_brkm(TBROK, cleanup, "sync_pipe_close failed"); /* do an assignement for fun */ memcpy(test, &stat_i, sizeof(stat_i)); /* pause until we get a signal from stat_cleanup() */ rval = pause(); /* now we're back - detach the memory and exit */ if (shmdt(test) == -1) { tst_resm(TBROK, "shmdt() failed - %d", errno); } tst_exit(); }
/* * stat_setup() - Set up for the IPC_STAT command with shmctl(). * Make things interesting by forking some children * that will either attach or inherit the shared memory. */ static void stat_setup(void) { int i, rval; void *test; pid_t pid; sigset_t newmask, oldmask; /* * The first time through, let the children attach the memory. * The second time through, attach the memory first and let * the children inherit the memory. */ if (stat_time == SECOND) { /* * use the global "set_shared" variable here so that * it can be removed in the stat_func() routine. */ 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_brkm(TBROK | TERRNO, cleanup, "block SIGUSR1 error"); for (i = 0; i < N_ATTACH; i++) { switch (pid = fork()) { case -1: tst_brkm(TBROK | TERRNO, cleanup, "fork"); case 0: test = (stat_time == FIRST) ? set_shmat() : set_shared; /* 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_brkm(TBROK | TERRNO, cleanup, "sigsuspend"); /* * don't have to block SIGUSR1 any more, * recover the mask */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) tst_brkm(TBROK | TERRNO, cleanup, "child sigprocmask"); /* now we're back - detach the memory and exit */ if (shmdt(test) == -1) tst_brkm(TBROK | TERRNO, cleanup, "shmdt in stat_setup()"); 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_brkm(TBROK, cleanup, "parent sigprocmask"); usleep(250000); }