void task_waiter_init(task_waiter_t *t) { datagen((void *)&t->seed, sizeof(t->seed), NULL); t->seed = t->seed % TASK_WAITER_INITIAL; if (pipe(t->pipes)) { pr_perror("task_waiter_init failed"); exit(1); } }
static int make_map(struct map *map) { uint32_t crc; uint8_t buf[ONE_MAP_SIZE]; static int i = 0; if (!(map->flag & MAP_ANONYMOUS)) { /* need file */ if (snprintf(map->filename, sizeof(map->filename), "%s-%02d", filename, i++) >= sizeof(map->filename)) { err("filename %s is too long\n", filename); return -1; } map->fd = open(map->filename, O_RDWR | O_CREAT, 0600); if (map->fd < 0) { err("can't open %s: %m\n", map->filename); return -1; } crc = ~0; datagen(buf, sizeof(buf), &crc); if (write(map->fd, buf, sizeof(buf)) != sizeof(buf)) { err("failed to write %s: %m\n", map->filename); return -1; } } map->ptr = mmap(NULL, ONE_MAP_SIZE, map->prot, map->flag, map->fd, 0); if (map->ptr == MAP_FAILED) { err("can't create mapping: %m\n"); return -1; } if ((map->flag & MAP_ANONYMOUS) && (map->prot & PROT_WRITE)) { /* can't fill it with data otherwise */ crc = ~0; datagen(map->ptr, ONE_MAP_SIZE, &crc); } return 0; }
int send_siginfo(int signo, pid_t pid, pid_t tid, int group, siginfo_t *info) { static int si_code = -10; uint32_t crc = ~0; info->si_code = si_code; si_code--; info->si_signo = signo; datagen((uint8_t *) siginf_body(info), _si_fields_sz, &crc); sent_sigs++; if (group) return syscall(SYS_rt_sigqueueinfo, pid, signo, info); else return syscall(SYS_rt_tgsigqueueinfo, pid, tid, signo, info); }
int send_siginfo(int signo, pid_t pid, pid_t tid, int group, siginfo_t *info) { static int si_code = -10; uint32_t crc = ~0; info->si_code = si_code; si_code--; info->si_signo = signo; datagen((uint8_t *) &info->_sifields, sizeof(siginfo_t) - offsetof(siginfo_t, _sifields), &crc); sent_sigs++; if (group) return syscall(SYS_rt_sigqueueinfo, pid, signo, info); else return syscall(SYS_rt_tgsigqueueinfo, pid, tid, signo, info); }
static int fill_shm_seg(int id, size_t size) { uint8_t *mem; uint32_t crc = INIT_CRC; mem = shmat(id, NULL, 0); if (mem == (void *)-1) { pr_perror("Can't attach shm: %d", -errno); return -1; } datagen(mem, size, &crc); if (shmdt(mem) < 0) { pr_perror("Can't detach shm: %d", -errno); return -1; } return 0; }
int main(int argc, char ** argv) { void *m; uint32_t crc; int i; test_init(argc, argv); m = mmap(NULL, MEM_SIZE, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (m == MAP_FAILED) { fail(); return 1; } crc = ~0; datagen(m, MEM_SIZE, &crc); for (i = 0; i < MEM_SIZE / (1<<20); i++) if (mprotect(m + (lrand48() * PAGE_SIZE % MEM_SIZE), PAGE_SIZE, PROT_NONE)) { err("mprotect"); return 1; } test_daemon(); test_waitsig(); if (mprotect(m, MEM_SIZE, PROT_READ)) err("mprotect"); crc = ~0; if (datachk(m, MEM_SIZE, &crc)) fail("Mem corrupted"); else pass(); return 0; }
static void run_child(int num) { int fd = fds[num][1]; uint32_t crc = ~0; size_t buf_size=512; uint8_t buf[buf_size]; struct timeval tv; struct timespec ts; int rv; close(fds[num][0]); datagen(buf, sizeof(buf), &crc); if (gettimeofday(&tv, NULL) < 0) { rv = GETTIMEOFDAYERROR; goto out; } srand(tv.tv_sec + tv.tv_usec); ts.tv_sec = 0; while (!stop) { ts.tv_nsec = rand() % 999999999; nanosleep(&ts, &ts); if (write(fd, buf, buf_size) < 0 && (!stop /* signal SIGUSR2 NOT received */ || (errno != EINTR && errno != EPIPE))) { fail("child write: %m\n"); rv = WRITEERROR; goto out; } } rv = SUCCESS; out: close(fds[num][1]); exit(rv); }
static int child(key_t key) { int sem, shm, ret, res = 0; uint8_t *mem; uint32_t crc; sem = semget(key, 1, 0777); if (sem == -1) return -1; shm = shmget(key, shmem_size, 0777); if (shm == -1) return -2; mem = shmat(shm, NULL, 0); if (mem == (uint8_t *)-1) return -3; while (test_go()) { ret = semop(sem, &lock, 1); if (ret) { if (errno == EINTR) continue; fail("Error in semop lock"); res = errno; break; } crc = INIT_CRC; datagen(mem, shmem_size, &crc); while ((ret = semop(sem, &unlock, 1)) && (errno == EINTR)); if (ret) { fail("Error in semop unlock"); res = errno; break; } } shmdt(mem); return res; }
int main(int argc, char **argv) { int ret = 0; int readfd, writefd; mode_t mode = S_IFIFO | 0600; char path[PROCS_DEF][BUF_SIZE]; pid_t pid; int i; uint8_t buf[0x100000]; int chret; char *file_path; test_init(argc, argv); for (i = 0; i < PROCS_DEF; i++) { file_path = path[i]; if (snprintf(file_path, BUF_SIZE, "%s-%02d", filename, i) >= BUF_SIZE) { pr_perror("filename %s is too long", filename); exit(1); } if (mkfifo(file_path, mode)) { pr_perror("can't make fifo \"%s\"", file_path); exit(1); } } pid = test_fork(); if (pid < 0) { pr_perror("Can't fork"); kill(0, SIGKILL); exit(1); } if (pid == 0) { file_path = path[0]; readfd = open(file_path, O_RDONLY); if (readfd < 0) { pr_perror("open(%s, O_RDONLY) Failed", file_path); ret = errno; return ret; } file_path = path[1]; writefd = open(file_path, O_WRONLY); if (writefd < 0) { pr_perror("open(%s, O_WRONLY) Failed", file_path); ret = errno; return ret; } if (pipe_in2out(readfd, writefd, buf, sizeof(buf)) < 0) /* pass errno as exit code to the parent */ if (test_go() /* signal NOT delivered */ || (errno != EINTR && errno != EPIPE)) ret = errno; close(readfd); close(writefd); exit(ret); } file_path = path[0]; writefd = open(file_path, O_WRONLY); if (writefd < 0) { pr_perror("open(%s, O_WRONLY) Failed", file_path); kill(pid, SIGKILL); return 1; } file_path = path[1]; readfd = open(file_path, O_RDONLY); if (readfd < 0) { pr_perror("open(%s, O_RDONLY) Failed", file_path); kill(pid, SIGKILL); return 1; } test_daemon(); while (test_go()) { int len, rlen = 0, wlen; uint8_t rbuf[sizeof(buf)], *p; datagen(buf, sizeof(buf), NULL); wlen = write(writefd, buf, sizeof(buf)); if (wlen < 0) { if (errno == EINTR) continue; else { fail("write failed: %m\n"); ret = 1; break; } } for (p = rbuf, len = wlen; len > 0; p += rlen, len -= rlen) { rlen = read(readfd, p, len); if (rlen <= 0) break; } if (rlen < 0 && errno == EINTR) continue; if (len > 0) { fail("read failed: %m\n"); ret = 1; break; } if (memcmp(buf, rbuf, wlen)) { fail("data mismatch\n"); ret = 1; break; } } close(writefd); test_waitsig(); wait(&chret); chret = WEXITSTATUS(chret); if (chret) { fail("child exited with non-zero code %d (%s)\n", chret, strerror(chret)); return 1; } if (!ret) pass(); close(readfd); for (i = 0; i < PROCS_DEF; i++) unlink(path[i]); return 0; }
int main(int argc, char **argv) { unsigned char buf[BUF_SIZE]; int fd, fd_s; pid_t extpid; uint32_t crc; int pfd[2]; int val; socklen_t optlen; if (pipe(pfd)) { err("pipe() failed"); return 1; } extpid = fork(); if (extpid < 0) { err("fork() failed"); return 1; } else if (extpid == 0) { test_ext_init(argc, argv); close(pfd[1]); if (read(pfd[0], &port, sizeof(port)) != sizeof(port)) { err("Can't read port\n"); return 1; } fd = tcp_init_client(ZDTM_FAMILY, "localhost", port); if (fd < 0) return 1; #ifdef STREAM while (1) { if (read_data(fd, buf, BUF_SIZE)) { err("read less then have to"); return 1; } if (datachk(buf, BUF_SIZE, &crc)) return 2; datagen(buf, BUF_SIZE, &crc); if (write_data(fd, buf, BUF_SIZE)) { err("can't write"); return 1; } } #else if (read_data(fd, buf, BUF_SIZE)) { err("read less then have to"); return 1; } if (datachk(buf, BUF_SIZE, &crc)) return 2; datagen(buf, BUF_SIZE, &crc); if (write_data(fd, buf, BUF_SIZE)) { err("can't write"); return 1; } #endif return 0; } test_init(argc, argv); if ((fd_s = tcp_init_server(ZDTM_FAMILY, &port)) < 0) { err("initializing server failed"); return 1; } close(pfd[0]); if (write(pfd[1], &port, sizeof(port)) != sizeof(port)) { err("Can't send port"); return 1; } close(pfd[1]); /* * parent is server of TCP connection */ fd = tcp_accept_server(fd_s); if (fd < 0) { err("can't accept client connection %m"); return 1; } val = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) { err("setsockopt"); return 1; } test_daemon(); #ifdef STREAM while (test_go()) { datagen(buf, BUF_SIZE, &crc); if (write_data(fd, buf, BUF_SIZE)) { err("can't write"); return 1; } if (read_data(fd, buf, BUF_SIZE)) { err("read less then have to"); return 1; } if (datachk(buf, BUF_SIZE, &crc)) return 2; } kill(extpid, SIGKILL); #else test_waitsig(); datagen(buf, BUF_SIZE, &crc); if (write_data(fd, buf, BUF_SIZE)) { err("can't write"); return 1; } if (read_data(fd, buf, BUF_SIZE)) { err("read less then have to"); return 1; } if (datachk(buf, BUF_SIZE, &crc)) return 2; #endif optlen = sizeof(val); if (getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, &optlen)) { err("getsockopt"); return 1; } if (val != 1) { fail("SO_REUSEADDR are not set for %d\n", fd); return 1; } pass(); return 0; }
int main(int argc, char **argv) { int ret = 0; int readfd, writefd; mode_t mode = S_IFIFO | 0644; char path[PROCS_DEF][BUF_SIZE]; pid_t pid; int i; uint8_t buf[0x100000]; char *file_path; test_init(argc, argv); for (i = 0; i < PROCS_DEF; i++) { file_path = path[i]; if (snprintf(file_path, BUF_SIZE, "%s-%02d", filename, i) >= BUF_SIZE) { err("filename %s is too long\n", filename); exit(1); } if (mkfifo(file_path, mode)) { err("can't make fifo \"%s\": %m\n", file_path); exit(1); } } if (signal(SIGCHLD, inc_num_exited) == SIG_ERR) { err("can't set SIGCHLD handler: %m\n"); exit(1); } for (i = 1; i < num_procs; i++) { /* i = 0 - parent */ pid = test_fork(); if (pid < 0) { err("Can't fork: %m\n"); kill(0, SIGKILL); exit(1); } if (pid == 0) { file_path = path[i - 1]; readfd = open(file_path, O_RDONLY); if (readfd < 0) { err("open(%s, O_RDONLY) Failed: %m\n", file_path); ret = errno; return ret; } file_path = path[i]; writefd = open(file_path, O_WRONLY); if (writefd < 0) { err("open(%s, O_WRONLY) Failed: %m\n", file_path); ret = errno; return ret; } signal(SIGPIPE, SIG_IGN); if (pipe_in2out(readfd, writefd, buf, sizeof(buf)) < 0) /* pass errno as exit code to the parent */ if (test_go() /* signal NOT delivered */ || (errno != EINTR && errno != EPIPE)) ret = errno; close(readfd); close(writefd); exit(ret); } pids[i] = pid; } file_path = path[0]; writefd = open(file_path, O_WRONLY); if (writefd < 0) { err("open(%s, O_WRONLY) Failed: %m\n", file_path); kill(0, SIGKILL); exit(1); } file_path = path[i - 1]; readfd = open(file_path, O_RDONLY); if (readfd < 0) { err("open(%s, O_RDONLY) Failed: %m\n", file_path); kill(0, SIGKILL); exit(1); } if (num_exited) { err("Some children died unexpectedly\n"); kill(0, SIGKILL); exit(1); } test_daemon(); while (test_go()) { int len, rlen = 0, wlen; uint8_t rbuf[sizeof(buf)], *p; datagen(buf, sizeof(buf), NULL); wlen = write(writefd, buf, sizeof(buf)); if (wlen < 0) { if (errno == EINTR) continue; else { fail("write failed: %m\n"); ret = 1; break; } } for (p = rbuf, len = wlen; len > 0; p += rlen, len -= rlen) { rlen = read(readfd, p, len); if (rlen <= 0) break; } if (rlen < 0 && errno == EINTR) continue; if (len > 0) { fail("read failed: %m\n"); ret = 1; break; } if (memcmp(buf, rbuf, wlen)) { fail("data mismatch\n"); ret = 1; break; } } close(writefd); test_waitsig(); /* even if failed, wait for migration to complete */ if (kill(0, SIGTERM)) { fail("failed to send SIGTERM to my process group: %m\n"); return 1; /* shouldn't wait() in this case */ } close(readfd); for (i = 1; i < num_procs; i++) { /* i = 0 - parent */ int chret; if (waitpid(pids[i], &chret, 0) < 0) { fail("waitpid error: %m\n"); ret = 1; continue; } chret = WEXITSTATUS(chret); if (chret) { fail("child %d exited with non-zero code %d (%s)\n", i, chret, strerror(chret)); ret = 1; continue; } } if (!ret) pass(); for (i = 0; i < PROCS_DEF; i++) unlink(path[i]); return 0; }
int main(int argc, char ** argv) { int sock, acc_sock, ret; char path[256]; pid_t pid; uint32_t crc; uint8_t buf[1000]; test_init(argc, argv); if (snprintf(path, sizeof(path), "%s/foo", dirname) >= sizeof(path)) { err("directory name \"%s\"is too long", dirname); exit(1); } if (mkdir(dirname, 0700)) { err("can't make directory %s: %m\n", dirname); exit(1); } sock = setup_srv_sock(path); if (sock < 0) goto out; pid = fork(); if (pid < 0) { err("can't fork: %m\n"); goto out; } if (pid == 0) { /* child writes to the overmounted socket and returns */ close(sock); sock = setup_clnt_sock(path); if (sock < 0) _exit(1); test_waitsig(); crc = ~0; datagen(buf, sizeof(buf), &crc); if (write(sock, buf, sizeof(buf)) != sizeof(buf)) _exit(errno); close(sock); _exit(0); } acc_sock = accept(sock, NULL, NULL); if (acc_sock < 0) { err("can't accept() the connection on \"%s\": %m", path); goto out_kill; } close(sock); sock = acc_sock; if (mount("rien", dirname, "tmpfs", 0, 0) < 0) { err("can't mount tmpfs over %s: %m", dirname); goto out_kill; } test_daemon(); test_waitsig(); if (kill(pid, SIGTERM)) { fail("terminating the child failed: %m\n"); goto out; } if (wait(&ret) != pid) { fail("wait() returned wrong pid %d: %m\n", pid); goto out; } if (WIFEXITED(ret)) { ret = WEXITSTATUS(ret); if (ret) { fail("child exited with nonzero code %d (%s)\n", ret, strerror(ret)); goto out; } } if (WIFSIGNALED(ret)) { fail("child exited on unexpected signal %d\n", WTERMSIG(ret)); goto out; } if (read(sock, buf, sizeof(buf)) != sizeof(buf)) { fail("can't read %s: %m\n", path); goto out; } crc = ~0; if (datachk(buf, sizeof(buf), &crc)) { fail("CRC mismatch\n"); goto out; } if (umount(dirname) < 0) { fail("can't umount %s: %m", dirname); goto out; } if (close(sock) < 0) { fail("can't close %s: %m", path); goto out; } if (unlink(path) < 0) { fail("can't unlink %s: %m", path); goto out; } pass(); out_kill: kill(pid, SIGKILL); out: close(sock); unlink(path); rmdir(dirname); return 0; }
int main(int argc, char ** argv) { int fd; size_t fsize=1000; mode_t mode; uid_t uid; gid_t gid; uint8_t buf[fsize]; struct stat fst; uint32_t crc; #ifdef UNLINK_FSTAT04 char filename[PATH_MAX]; #endif test_init(argc, argv); #ifdef UNLINK_FSTAT04 snprintf(filename, sizeof(filename), "%s/test\\file'\n\"un%%linkfstat00", dirname); mkdir(dirname, 0700); #endif fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0644); if (fd < 0) { pr_perror("can't open %s", filename); exit(1); } #ifdef UNLINK_FSTAT04 if (chmod(dirname, 0500)) { pr_perror("chmod"); exit(1); } #endif if (fstat(fd, &fst) < 0) { pr_perror("can't get file info %s before", filename); goto failed; } if (unlink(filename) < 0) { pr_perror("can't unlink %s", filename); goto failed; } /* Change file size */ if (fst.st_size != 0) { pr_perror("%s file size eq %d", fst.st_size); goto failed; } crc = ~0; datagen(buf, sizeof(buf), &crc); if (write(fd, buf, sizeof(buf)) != sizeof(buf)) { pr_perror("can't write %s", filename); goto failed; } /* Change file mode */ if ((fst.st_mode & S_IXOTH) == 0) mode = (fst.st_mode | S_IXOTH); else mode = (fst.st_mode ^ S_IXOTH); if (fchmod(fd, mode) < 0) { pr_perror("can't chmod %s", filename); goto failed; } if (getuid()) { uid = getuid(); gid = getgid(); } else { /* Change uid, gid */ if (fchown(fd, (uid = fst.st_uid + 1), (gid = fst.st_gid + 1)) < 0) { pr_perror("can't chown %s", filename); goto failed; } } if (lseek(fd, 0, SEEK_SET) != 0) { pr_perror("can't reposition to 0"); goto failed; } test_daemon(); test_waitsig(); if (fstat(fd, &fst) < 0) { pr_perror("can't get %s file info after", filename); goto failed; } /* Check file size */ if (fst.st_size != fsize) { fail("(via fstat): file size changed to %d", fst.st_size); goto failed; } fst.st_size = lseek(fd, 0, SEEK_END); if (fst.st_size != fsize) { fail("(via lseek): file size changed to %d", fst.st_size); goto failed; } /* Check mode */ if (fst.st_mode != mode) { fail("mode is changed to %o(%o)", fst.st_mode, mode); goto failed; } /* Check uid, gid */ if (fst.st_uid != uid || fst.st_gid != gid) { fail("u(g)id changed: uid=%d(%d), gid=%d(%d)", fst.st_uid, uid, fst.st_gid, gid); goto failed; } if (lseek(fd, 0, SEEK_SET) != 0) { pr_perror("can't reposition to 0"); goto failed; } if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { fail("can't read %s: %m\n", filename); goto failed; } crc = ~0; if (datachk(buf, sizeof(buf), &crc)) { fail("CRC mismatch\n"); goto failed; } close(fd); pass(); return 0; failed: unlink(filename); close(fd); return 1; }
int main(int argc, char ** argv) { int sock, acc_sock, ret; pid_t pid; uint32_t crc; uint8_t buf[1000]; test_init(argc, argv); sock = setup_srv_sock(); if (sock < 0) exit(1); pid = test_fork(); if (pid < 0) { pr_perror("can't fork"); exit(1); } if (pid == 0) { /* child writes to the unlinked socket and returns */ close(sock); sock = setup_clnt_sock(); if (sock < 0) _exit(1); test_waitsig(); crc = ~0; datagen(buf, sizeof(buf), &crc); if (write(sock, buf, sizeof(buf)) != sizeof(buf)) { pr_perror("can't write to socket"); exit(errno); } close(sock); exit(0); } acc_sock = accept(sock, NULL, NULL); if (acc_sock < 0) { pr_perror("can't accept() the connection on \"%s\"", filename); goto out_kill; } close(sock); sock = acc_sock; if (unlink(filename)) { pr_perror("can't unlink %s", filename); goto out_kill; } test_daemon(); test_waitsig(); if (kill(pid, SIGTERM)) { fail("terminating the child failed: %m\n"); goto out; } if (wait(&ret) != pid) { fail("wait() returned wrong pid %d: %m\n", pid); goto out; } if (WIFEXITED(ret)) { ret = WEXITSTATUS(ret); if (ret) { fail("child exited with nonzero code %d (%s)\n", ret, strerror(ret)); goto out; } } if (WIFSIGNALED(ret)) { fail("child exited on unexpected signal %d\n", WTERMSIG(ret)); goto out; } if (read(sock, buf, sizeof(buf)) != sizeof(buf)) { fail("can't read %s: %m\n", filename); goto out; } crc = ~0; if (datachk(buf, sizeof(buf), &crc)) { fail("CRC mismatch\n"); goto out; } if (close(sock)) { fail("close failed: %m\n"); goto out; } if (unlink(filename) != -1 || errno != ENOENT) { fail("file %s should have been deleted before migration: unlink: %m\n", filename); goto out; } pass(); out_kill: kill(pid, SIGTERM); out: close(sock); return 0; }
int main(int argc, char ** argv) { void *m, *m2; char path[PATH_MAX]; uint32_t crc; pid_t pid = -1; int status, fd; test_init(argc, argv); m = mmap(NULL, MEM_SIZE, PROT_WRITE | PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (m == MAP_FAILED) goto err; pid = test_fork(); if (pid < 0) { goto err; } else if (pid == 0) { crc = ~0; datagen(m + MEM_OFFSET, PAGE_SIZE, &crc); crc = ~0; datagen(m + MEM_OFFSET2, PAGE_SIZE, &crc); test_waitsig(); crc = ~0; status = datachk(m + MEM_OFFSET, PAGE_SIZE, &crc); if (status) return 1; crc = ~0; status = datachk(m + MEM_OFFSET2, PAGE_SIZE, &crc); if (status) return 1; crc = ~0; status = datachk(m + PAGE_SIZE, PAGE_SIZE, &crc); if (status) return 1; return 0; } snprintf(path, PATH_MAX, "/proc/self/map_files/%lx-%lx", (unsigned long) m, (unsigned long) m + MEM_SIZE); fd = open(path, O_RDWR); if (fd == -1) { err("Can't open file %s: %m", path); goto err; } m2 = mmap(NULL, PAGE_SIZE, PROT_WRITE | PROT_READ, MAP_SHARED, fd, MEM_OFFSET3); if (m2 == MAP_FAILED) { err("Can't map file %s", path); goto err; } close(fd); munmap(m, PAGE_SIZE); munmap(m + PAGE_SIZE * 10, PAGE_SIZE); munmap(m + MEM_OFFSET2, PAGE_SIZE); crc = ~0; datagen(m + PAGE_SIZE, PAGE_SIZE, &crc); crc = ~0; datagen(m2, PAGE_SIZE, &crc); test_daemon(); test_waitsig(); kill(pid, SIGTERM); wait(&status); if (WIFEXITED(status)) { if (WEXITSTATUS(status)) goto err; } else goto err; crc = ~0; if (datachk(m + MEM_OFFSET, PAGE_SIZE, &crc)) goto err; crc = ~0; if (datachk(m2, PAGE_SIZE, &crc)) goto err; pass(); return 0; err: if (waitpid(-1, NULL, WNOHANG) == 0) { kill(pid, SIGTERM); wait(NULL); } return 1; }
int main(int argc, char **argv) { unsigned char buf[BUF_SIZE]; int fd, fd_s; int status; pid_t pid; int res; uint32_t crc; struct sigaction sa = { .sa_handler = sig_hand, /* don't set SA_RESTART */ }; test_init(argc, argv); if ((fd_s = tcp_init_server(ZDTM_FAMILY, &port)) < 0) { err("initializing server failed"); return 1; } test_daemon(); test_waitsig(); sigemptyset(&sa.sa_mask); if (sigaction(SIGCHLD, &sa, NULL)) fprintf(stderr, "Can't set SIGTERM handler: %m\n"); pid = test_fork(); if (pid < 0) { err("fork failed. Return %d %m", pid); return 1; } if (pid == 0) { /* * Chiled is client of TCP connection */ close(fd_s); fd = tcp_init_client(ZDTM_FAMILY, "localhost", port); if (fd < 0) return 1; res = read(fd, buf, BUF_SIZE); close(fd); if (res != BUF_SIZE) { err("read less then have to: %d instead of %d", res, BUF_SIZE); return -1; } if (datachk(buf, BUF_SIZE, &crc)) return -2; return 0; } /* * parent is server of TCP connection */ fd = tcp_accept_server(fd_s); close(fd_s); if (fd < 0) { err("can't accept client connection %m"); goto error; } datagen(buf, BUF_SIZE, &crc); if (write(fd, buf, BUF_SIZE) < BUF_SIZE) { err("can't write"); goto error; } close(fd); if (wait(&status) < 0) { err("wait failed %m"); goto error; } if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { err("chiled failed. Return %d", WEXITSTATUS(status)); return 1; } pass(); return 0; error: kill(pid, SIGKILL); wait(&status); return -1; }
int main(int argc, char **argv) { int ret = 0; pid_t pid; int i; uint8_t buf[0x100000]; int pipes[PROCS_MAX * 2]; int in, out; test_init(argc, argv); if (num_procs > PROCS_MAX) { err("%d processes is too many: max = %d\n", num_procs, PROCS_MAX); exit(1); } for (i = 0; i < num_procs; i++) if (pipe(pipes + i * 2)) { err("Can't create pipes: %m\n"); exit(1); } if (signal(SIGCHLD, inc_num_exited) == SIG_ERR) { err("can't set SIGCHLD handler: %m\n"); exit(1); } for (i = 1; i < num_procs; i++) { /* i = 0 - parent */ pid = test_fork(); if (pid < 0) { err("Can't fork: %m\n"); kill(0, SIGKILL); exit(1); } if (pid == 0) { int j; in = i * 2; out = in - 1; for (j = 0; j < num_procs * 2; j++) if (j != in && j != out) close(pipes[j]); signal(SIGPIPE, SIG_IGN); if (pipe_in2out(pipes[in], pipes[out], buf, sizeof(buf)) < 0) /* pass errno as exit code to the parent */ if (test_go() /* signal NOT delivered */ || (errno != EINTR && errno != EPIPE)) ret = errno; test_waitsig(); /* even if failed, wait for migration to complete */ close(pipes[in]); close(pipes[out]); exit(ret); } } for (i = 1; i < num_procs * 2 - 1; i++) close(pipes[i]); in = pipes[0]; out = pipes[num_procs * 2 - 1]; /* don't block on writing, _do_ block on reading */ if (set_nonblock(out,1) < 0) { err("setting O_NONBLOCK failed: %m"); exit(1); } if (num_exited) { err("Some children died unexpectedly\n"); kill(0, SIGKILL); exit(1); } test_daemon(); while (test_go()) { int len, rlen = 0, wlen; uint8_t rbuf[sizeof(buf)], *p; datagen(buf, sizeof(buf), NULL); wlen = write(out, buf, sizeof(buf)); if (wlen < 0) { if (errno == EINTR) continue; else { fail("write failed: %m\n", i); ret = 1; break; } } for (p = rbuf, len = wlen; len > 0; p += rlen, len -= rlen) { rlen = read(in, p, len); if (rlen <= 0) break; } if (rlen < 0 && errno == EINTR) continue; if (len > 0) { fail("read failed: %m\n"); ret = 1; break; } if (memcmp(buf, rbuf, wlen)) { fail("data mismatch\n"); ret = 1; break; } } close(out); test_waitsig(); /* even if failed, wait for migration to complete */ if (kill(0, SIGTERM)) { fail("failed to send SIGTERM to my process group: %m\n"); goto out; /* shouldn't wait() in this case */ } for (i = 1; i < num_procs; i++) { /* i = 0 - parent */ int chret; if (wait(&chret) < 0) { fail("can't wait for a child: %m\n"); ret = 1; continue; } chret = WEXITSTATUS(chret); if (chret) { fail("child %d exited with non-zero code %d (%s)\n", i, chret, strerror(chret)); ret = 1; continue; } } if (!ret) pass(); out: close(in); return 0; }
int main(int argc, char ** argv) { int fd; struct stat st; uint32_t crc; bool chk_hole = true; test_init(argc, argv); fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0644); if (fd < 0) { pr_perror("can't open %s", filename); exit(1); } if (unlink(filename) < 0) { pr_perror("can't unlink %s", filename); goto failed; } crc = ~0; datagen(buf4k, BUFSIZE, &crc); if (pwrite(fd, buf4k, BUFSIZE, DATA1_OFF) != BUFSIZE) { pr_perror("can't write data1"); goto failed; } crc = ~0; datagen(buf4k, BUFSIZE, &crc); if (pwrite(fd, buf4k, BUFSIZE, DATA2_OFF) != BUFSIZE) { pr_perror("can't write data2"); goto failed; } if (ftruncate(fd, FILE_SIZE)) { pr_perror("Can't fixup file size"); goto failed; } if (lseek(fd, DATA1_OFF, SEEK_HOLE) != DATA1_OFF + BUFSIZE) { test_msg("Won't check for hole\n"); chk_hole = false; } test_daemon(); test_waitsig(); if (fstat(fd, &st) < 0) { fail("can't stat after"); goto failed; } if (st.st_size != FILE_SIZE) { fail("file size changed to %ld", (long)st.st_size); goto failed; } test_msg("Blocks %u OK\n", FILE_BLOCKS); /* Data 1 */ if (pread(fd, buf4k, BUFSIZE, DATA1_OFF) != BUFSIZE) { fail("pread1 fail"); goto failed; } crc = ~0; if (datachk(buf4k, BUFSIZE, &crc)) { fail("datachk1 fail"); goto failed; } test_msg("Data @%u OK\n", DATA1_BLK); /* Data 2 */ if (pread(fd, buf4k, BUFSIZE, DATA2_OFF) != BUFSIZE) { fail("pread2 fail"); goto failed; } crc = ~0; if (datachk(buf4k, BUFSIZE, &crc)) { fail("datachk2 fail"); goto failed; } test_msg("Data @%u OK\n", DATA2_BLK); /* Hole */ if (chk_hole) { #ifdef HEAD_HOLE if (lseek(fd, 0, SEEK_HOLE) != 0) { fail("hh not found"); goto failed; } test_msg("Head hole OK\n"); #endif if (lseek(fd, DATA1_OFF, SEEK_HOLE) != DATA1_OFF + BUFSIZE) { fail("mh not found"); goto failed; } test_msg("Mid hole OK\n"); #ifdef TAIL_HOLE if (lseek(fd, DATA2_OFF, SEEK_HOLE) != DATA2_OFF + BUFSIZE) { fail("tail hole not found"); goto failed; } test_msg("Tail hole OK\n"); #endif } close(fd); pass(); return 0; failed: close(fd); return 1; }
int main(int argc, char **argv) { int ret = 0; pid_t pid; int i; uint8_t buf[0x100000]; int socks[PROCS_MAX * 2]; int in, out; test_init(argc, argv); if (num_procs > PROCS_MAX) { err("%d processes is too many: max = %d\n", num_procs, PROCS_MAX); exit(1); } for (i = 0; i < num_procs; i++) if (socketpair(AF_LOCAL, SOCK_STREAM, 0, socks + i * 2)) { err("Can't create socks: %m\n"); exit(1); } if (signal(SIGCHLD, inc_num_exited) == SIG_ERR) { err("can't set SIGCHLD handler: %m\n"); exit(1); } for (i = 1; i < num_procs; i++) { /* i = 0 - parent */ pid = test_fork(); if (pid < 0) { err("Can't fork: %m\n"); kill(0, SIGKILL); exit(1); } if (pid == 0) { int j; in = i * 2; out = in - 1; for (j = 0; j < num_procs * 2; j++) if (j != in && j != out) close(socks[j]); signal(SIGPIPE, SIG_IGN); if (pipe_in2out(socks[in], socks[out], buf, sizeof(buf)) < 0) /* pass errno as exit code to the parent */ if (test_go() /* signal NOT delivered */ || (errno != EINTR && errno != EPIPE && errno != ECONNRESET)) ret = errno; test_waitsig(); /* even if failed, wait for migration to complete */ close(socks[in]); close(socks[out]); exit(ret); } } for (i = 1; i < num_procs * 2 - 1; i++) close(socks[i]); in = socks[0]; out = socks[num_procs * 2 - 1]; /* don't block on writing, _do_ block on reading */ if (set_nonblock(out,1) < 0) { err("setting O_NONBLOCK failed: %m"); exit(1); } if (num_exited) { err("Some children died unexpectedly\n"); kill(0, SIGKILL); exit(1); } test_daemon(); while (test_go()) { int len, rlen = 0, wlen; uint8_t rbuf[sizeof(buf)], *p; datagen(buf, sizeof(buf), NULL); wlen = write(out, buf, sizeof(buf)); if (wlen < 0) { if (errno == EINTR) continue; else { fail("write failed: %m\n", i); ret = 1; break; } } for (p = rbuf, len = wlen; len > 0; p += rlen, len -= rlen) { rlen = read(in, p, len); if (rlen <= 0) break; } if (rlen < 0 && errno == EINTR) continue; if (len > 0) { fail("read failed: %m\n"); ret = 1; break; } if (memcmp(buf, rbuf, wlen)) { fail("data mismatch\n"); ret = 1; break; } } test_waitsig(); /* even if failed, wait for migration to complete */ /* We expect that write(2) in child may return error only after signal * has been received. Thus, send signal before closing parent fds. */ if (kill(0, SIGTERM)) { fail("failed to send SIGTERM to my process group: %m\n"); goto out; /* shouldn't wait() in this case */ } if (close(out)) fail("Failed to close parent fd 'out': %m\n"); /* If last child in the chain (from whom we read data) receives signal * after parent has finished reading but before calling write(2), this * child can block forever. To avoid this, close 'in' fd. */ if (close(in)) fail("failed to close parent fd 'in': %m\n"); for (i = 1; i < num_procs; i++) { /* i = 0 - parent */ int chret; if (wait(&chret) < 0) { fail("can't wait for a child: %m\n"); ret = 1; continue; } chret = WEXITSTATUS(chret); if (chret) { fail("child %d exited with non-zero code %d (%s)\n", i, chret, strerror(chret)); ret = 1; continue; } } if (!ret) pass(); out: return 0; }