static int shmem_wait_and_open(int pid, struct shmem_info *si) { char path[128]; int ret; pr_info("Waiting for the %lx shmem to appear\n", si->shmid); futex_wait_while(&si->lock, 0); snprintf(path, sizeof(path), "/proc/%d/fd/%d", si->pid, si->fd); pr_info("Opening shmem [%s] \n", path); ret = open_proc_rw(si->pid, "fd/%d", si->fd); if (ret < 0) pr_perror(" %d: Can't stat shmem at %s", si->pid, path); futex_inc_and_wake(&si->lock); return ret; }
void test_waitsig(void) { futex_wait_while(&sig_received, 0); }
int main(int argc, char ** argv) { int i, err, ret; void *ptr; BUG_ON(sizeof(*fstate) + sizeof(__testcases) > 4096); ptr = mmap(NULL, 4096, PROT_WRITE | PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (ptr == MAP_FAILED) return 1; fstate = ptr; futex_set(fstate, TEST_FORK); testcases = ptr + sizeof(*fstate); memcpy(testcases, &__testcases, sizeof(__testcases)); test_init(argc, argv); testcases[0].master.pid = getpid();; if (child(0)) goto err; for (i = 1; i < TESTS; i++) { ret = futex_wait_while(&testcases[i].futex, 0); if (ret < 0) return 1; futex_set(&testcases[i].futex, 0); } test_msg("TEST_PGID\n"); futex_set_and_wake(fstate, TEST_PGID); for (i = 1; i < TESTS; i++) { ret = futex_wait_while(&testcases[i].futex, 0); if (ret < 0) goto err; futex_set(&testcases[i].futex, 0); } test_msg("TEST_WAIT\n"); futex_set_and_wake(fstate, TEST_WAIT); for (i = 1; i < TESTS; i++) { if (!testcases[i].alive) continue; ret = futex_wait_while(&testcases[i].futex, 0); if (ret < 0) goto err; futex_set(&testcases[i].futex, 0); } for (i = 0; i < TESTS; i++) { if (testcases[0].pid != testcases[i].ppid) continue; if (testcases[i].alive) continue; test_msg("Wait porcess %d (pid %d)\n", i, testcases[i].master.pid); waitpid(testcases[i].master.pid, NULL, 0); } test_msg("TEST_MASTER\n"); futex_set_and_wake(fstate, TEST_MASTER); for (i = 1; i < TESTS; i++) { if (!testcases[i].alive) continue; ret = futex_wait_while(&testcases[i].futex, 0); if (ret < 0) goto err; futex_set(&testcases[i].futex, 0); test_msg("The process %d initilized\n", ret); } test_daemon(); test_waitsig(); err = 0; for (i = 1; i < TESTS; i++) { int j; struct testcase *t = testcases + i; pid_t sid, pgid; if (!t->alive) continue; for (j = 0; j < TESTS; j++) { struct testcase *p = testcases + j; /* sanity check */ if (p->pid == t->sid && t->master.sid != p->master.pid) { err("session mismatch (%d) %d != (%d) %d", i, t->master.sid, j, p->master.pid); err++; } if (p->pid == t->pgid && t->master.pgid != p->master.pid) { err("pgid mismatch (%d) %d != (%d) %d", i, t->master.pgid, j, p->master.pid); err++; } } sid = getsid(t->master.pid); if (t->master.sid != sid) { err("%d: session mismatch %d (expected %d)", i, sid, t->master.sid); err++; } pgid = getpgid(t->master.pid); if (t->master.pgid != pgid) { err("%d: pgid mismatch %d (expected %d)", i, t->master.pgid, pgid); err++; } } test_msg("TEST_CHECK\n"); futex_set_and_wake(fstate, TEST_CHECK); for (i = 1; i < TESTS; i++) { if (!testcases[i].alive) continue; ret = futex_wait_while(&testcases[i].futex, 0); if (ret < 0) goto err; futex_set(&testcases[i].futex, 0); if (ret < 0) { fail("Someone failed"); err++; continue; } test_msg("The process %u is restored correctly\n", (unsigned)ret); } test_msg("TEST_EXIT\n"); futex_set_and_wake(fstate, TEST_EXIT); if (!err) pass(); return 0; err: for (i = 1; i < TESTS; i++) { pid_t pid = testcases[i].master.pid; if (pid > 0) { ret = kill(pid, SIGKILL); test_msg("kill %d %s\n", pid, strerror(ret == -1 ? errno : 0)); } } return 1; }