mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-28 20:42:49 +00:00
Move static and transition into zdtm top. We can't move all the micro tests themselves, as we need to distinguish static from non static (zdtm.py makes additional checks on static ones). Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
207 lines
3.3 KiB
C
207 lines
3.3 KiB
C
#define _GNU_SOURCE /* See feature_test_macros(7) */
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <sched.h>
|
|
#include <signal.h>
|
|
#include <sys/wait.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "zdtmtst.h"
|
|
|
|
const char *test_doc = "Check a shared file descriptor table.";
|
|
const char *test_author = "Andrew Vagin <avagin@openvz.org>";
|
|
|
|
char *filename;
|
|
TEST_OPTION(filename, string, "file name", 1);
|
|
|
|
#define STACK_SIZE 4096
|
|
#define TEST_FD 128
|
|
#define TEST_STRING "Hello World!"
|
|
|
|
#define CHILDREN 4
|
|
static int fork_pfd[2];
|
|
|
|
static void forked()
|
|
{
|
|
char c = 0;
|
|
|
|
if (write(fork_pfd[1], &c, 1) != 1) {
|
|
pr_perror("Unable to send a signal to the parent");
|
|
exit(5);
|
|
}
|
|
}
|
|
|
|
static void wait_children()
|
|
{
|
|
int i;
|
|
char c;
|
|
|
|
for (i = 0; i < CHILDREN; i++) {
|
|
if (read(fork_pfd[0], &c, 1) != 1) {
|
|
pr_perror("Unable to read a signal from a child");
|
|
exit(5);
|
|
}
|
|
}
|
|
}
|
|
|
|
static pid_t clone_child(int (*fn)(void *), int flags)
|
|
{
|
|
char stack[STACK_SIZE] __stack_aligned__;
|
|
pid_t pid;
|
|
|
|
pid = clone(fn, stack + STACK_SIZE,
|
|
flags | SIGCHLD, NULL);
|
|
if (pid == -1) {
|
|
pr_perror("Unable to clone a new process");
|
|
return -1;
|
|
}
|
|
|
|
return pid;
|
|
}
|
|
|
|
static int child2(void *_arg)
|
|
{
|
|
char buf[10];
|
|
|
|
forked();
|
|
test_waitsig();
|
|
|
|
if (read(TEST_FD, buf, sizeof(TEST_STRING)) != sizeof(TEST_STRING)) {
|
|
pr_perror("Unable to read from %d", TEST_FD);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int child3(void *_arg)
|
|
{
|
|
forked();
|
|
test_waitsig();
|
|
|
|
if (close(TEST_FD) != -1) {
|
|
fail("%d is exist\n", TEST_FD);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int child(void *_arg)
|
|
{
|
|
char buf[10];
|
|
pid_t pid, pid2;
|
|
int status;
|
|
|
|
pid = clone_child(child2, CLONE_FILES);
|
|
if (pid < 0)
|
|
return 1;
|
|
|
|
pid2 = clone_child(child3, 0);
|
|
if (pid < 0)
|
|
return 1;
|
|
|
|
forked();
|
|
test_waitsig();
|
|
|
|
kill(pid2, SIGTERM);
|
|
kill(pid, SIGTERM);
|
|
waitpid(pid2, &status, 0);
|
|
|
|
if (status) {
|
|
fail("The child3 returned %d\n", status);
|
|
return 1;
|
|
}
|
|
|
|
waitpid(pid, &status, 0);
|
|
|
|
if (status) {
|
|
fail("The child2 returned %d\n", status);
|
|
return 1;
|
|
}
|
|
|
|
if (read(TEST_FD, buf, sizeof(TEST_STRING)) != sizeof(TEST_STRING)) {
|
|
pr_perror("Unable to read from %d", TEST_FD);
|
|
return 1;
|
|
}
|
|
|
|
if (close(TEST_FD) == -1) {
|
|
pr_perror("Unable to close(%d)", TEST_FD);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char ** argv)
|
|
{
|
|
int status;
|
|
pid_t pid, pid2;
|
|
int fd, i;
|
|
|
|
test_init(argc, argv);
|
|
|
|
if (pipe(fork_pfd)) {
|
|
pr_perror("pipe");
|
|
return 1;
|
|
}
|
|
|
|
pid = clone_child(child, CLONE_FILES);
|
|
if (pid < 0)
|
|
return 1;
|
|
|
|
pid2 = clone_child(child2, CLONE_FILES);
|
|
if (pid2 < 0)
|
|
return 1;
|
|
|
|
wait_children();
|
|
|
|
test_daemon();
|
|
test_waitsig();
|
|
|
|
fd = open(filename, O_RDWR | O_CREAT, 0666);
|
|
if (fd == -1) {
|
|
pr_perror("Can't open /dev/zero");
|
|
return -1;
|
|
}
|
|
|
|
for (i = 0; i < 3; i++)
|
|
if (write(fd, TEST_STRING, sizeof(TEST_STRING)) != sizeof(TEST_STRING)) {
|
|
pr_perror("Unable to write a test string");
|
|
return -1;
|
|
}
|
|
|
|
fd = dup2(fd, TEST_FD);
|
|
if (fd == -1) {
|
|
pr_perror("Can't dup fd to %d", fd, TEST_FD);
|
|
return -1;
|
|
}
|
|
|
|
lseek(fd, 0, SEEK_SET);
|
|
|
|
kill(pid2, SIGTERM);
|
|
waitpid(pid2, &status, 0);
|
|
kill(pid, SIGTERM);
|
|
|
|
if (status) {
|
|
fail("The child returned %d\n", status);
|
|
return 1;
|
|
}
|
|
|
|
waitpid(pid, &status, 0);
|
|
if (status) {
|
|
fail("The child returned %d\n", status);
|
|
return 1;
|
|
}
|
|
|
|
if (close(TEST_FD) == 0) {
|
|
fail("%d was not closed\n", TEST_FD);
|
|
return 1;
|
|
}
|
|
|
|
pass();
|
|
|
|
return 0;
|
|
}
|