mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-29 21:12:29 +00:00
zdtm: move all logic about namespaces from test_init in libzdtm
A test will be executed in new set of namespaces if the environment variable ZDTM_NEWNS is set. A pid of the root task will be written in $ZDTM_PIDFILE and a root fyle system will be changed on $ZDTM_ROOT. Signed-off-by: Andrey Vagin <avagin@openvz.org> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
parent
aabb56bd66
commit
6aaf65642b
10 changed files with 392 additions and 264 deletions
30
test/zdtm.sh
30
test/zdtm.sh
|
|
@ -91,11 +91,20 @@ ARGS=""
|
|||
PID=""
|
||||
PIDNS=""
|
||||
|
||||
umount_zdtm_root()
|
||||
{
|
||||
[ -z "$ZDTM_ROOT" ] && return;
|
||||
umount -l "$ZDTM_ROOT"
|
||||
rmdir "$ZDTM_ROOT"
|
||||
}
|
||||
trap umount_zdtm_root EXIT
|
||||
|
||||
start_test()
|
||||
{
|
||||
local tdir=$1
|
||||
local tname=$2
|
||||
local tpid=$tdir/$tname.init.pid
|
||||
export ZDTM_ROOT
|
||||
TPID=`readlink -f $tdir`/$tname.init.pid
|
||||
|
||||
killall -9 $tname &> /dev/null
|
||||
make -C $tdir cleanout
|
||||
|
|
@ -104,12 +113,23 @@ start_test()
|
|||
make -C $tdir $tname.pid
|
||||
PID=`cat $test.pid` || return 1
|
||||
else
|
||||
$TINIT $tdir $tname $tpid || {
|
||||
if [ -z "$ZDTM_ROOT" ]; then
|
||||
mkdir dump
|
||||
ZDTM_ROOT=`mktemp -d dump/crtools-root.XXXXXX`
|
||||
ZDTM_ROOT=`readlink -f $ZDTM_ROOT`
|
||||
mount --bind . $ZDTM_ROOT || return 1
|
||||
fi
|
||||
( export ZDTM_NEWNS=1
|
||||
export ZDTM_PIDFILE=$TPID
|
||||
cd $ZDTM_ROOT
|
||||
rm -f $ZDTM_PIDFILE
|
||||
make -C $tdir $tname.pid || {
|
||||
echo ERROR: fail to start $tdir/$tname
|
||||
return 1;
|
||||
}
|
||||
)
|
||||
|
||||
PID=`cat $tpid`
|
||||
PID=`cat "$TPID"`
|
||||
ps -p $PID || return 1
|
||||
fi
|
||||
}
|
||||
|
|
@ -122,7 +142,7 @@ stop_test()
|
|||
if [ -z "$PIDNS" ]; then
|
||||
make -C $tdir $tname.out
|
||||
else
|
||||
killall test_init
|
||||
kill `cat "$TPID"`
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -170,7 +190,7 @@ run_test()
|
|||
DUMP_PATH=`pwd`/$ddump
|
||||
|
||||
if [ -n "$PIDNS" ]; then
|
||||
args="--namespace pid --namespace mnt $args"
|
||||
args="-n uts -n ipc -n net -n pid -n mnt --root $ZDTM_ROOT --pidfile $TPID $args"
|
||||
fi
|
||||
|
||||
echo Dump $PID
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
CFLAGS = -g -O2 -Wall -Werror -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
|
||||
CFLAGS = --static -g -O2 -Wall -Werror -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
|
||||
|
||||
LIB = libzdtmtst.a
|
||||
|
||||
LIBSRC = datagen.c msg.c parseargs.c test.c streamutil.c lock.c
|
||||
LIBSRC = datagen.c msg.c parseargs.c test.c streamutil.c lock.c ns.c
|
||||
LIBOBJ = $(LIBSRC:%.c=%.o)
|
||||
LIBDEP = $(LIBSRC:%.c=%.d)
|
||||
|
||||
|
|
@ -10,7 +10,7 @@ DEPEND.c = $(COMPILE.c) -MM -MP
|
|||
%.d: %.c
|
||||
$(DEPEND.c) $(OUTPUT_OPTION) $<
|
||||
|
||||
all: $(LIB) test_init
|
||||
all: $(LIB)
|
||||
install: all
|
||||
|
||||
$(LIB): $(LIB)(${LIBOBJ})
|
||||
|
|
|
|||
323
test/zdtm/lib/ns.c
Normal file
323
test/zdtm/lib/ns.c
Normal file
|
|
@ -0,0 +1,323 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <sched.h>
|
||||
|
||||
#include "ns.h"
|
||||
|
||||
extern int pivot_root(const char *new_root, const char *put_old);
|
||||
static int prepare_mntns()
|
||||
{
|
||||
FILE *f;
|
||||
unsigned fs_cnt, fs_cnt_last = 0;
|
||||
char buf[1024];
|
||||
char *root;
|
||||
|
||||
root = getenv("ZDTM_ROOT");
|
||||
fprintf(stderr, "'%s'\n", root);
|
||||
again:
|
||||
fs_cnt = 0;
|
||||
f = fopen("/proc/self/mountinfo", "r");
|
||||
if (!f) {
|
||||
fprintf(stderr, "Can't open mountinfo");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fgets(buf, sizeof(buf), f) != NULL) {
|
||||
char *mp = buf, *end;
|
||||
|
||||
mp = strchr(mp, ' ') + 1;
|
||||
mp = strchr(mp, ' ') + 1;
|
||||
mp = strchr(mp, ' ') + 1;
|
||||
mp = strchr(mp, ' ') + 1;
|
||||
end = strchr(mp, ' ');
|
||||
*end = '\0';
|
||||
|
||||
if (!strcmp(mp, "/"))
|
||||
continue;
|
||||
if (!strcmp(mp, "/proc"))
|
||||
continue;
|
||||
if (root && !strcmp(mp, root))
|
||||
continue;
|
||||
|
||||
fprintf(stderr, "%s\n", mp);
|
||||
if (umount(mp))
|
||||
fprintf(stderr, "%s - %m\n", mp);
|
||||
fs_cnt++;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
if (fs_cnt == 0)
|
||||
goto done;
|
||||
|
||||
if (fs_cnt != fs_cnt_last) {
|
||||
fs_cnt_last = fs_cnt;
|
||||
goto again;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Can't umount all the filesystems");
|
||||
return -1;
|
||||
done:
|
||||
if (root) {
|
||||
int dfd;
|
||||
|
||||
dfd = open(".", O_RDONLY);
|
||||
if (dfd == -1) {
|
||||
fprintf(stderr, "open(.) failed: %m\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (umount("/proc")) {
|
||||
fprintf(stderr, "umount(/proc) failed: %m\n");
|
||||
return -1;
|
||||
}
|
||||
if (chdir(root)) {
|
||||
fprintf(stderr, "chdir(%s) failed: %m\n", root);
|
||||
return -1;
|
||||
}
|
||||
if (mkdir("old", 0777) && errno != EEXIST) {
|
||||
fprintf(stderr, "mkdir(old) failed: %m\n");
|
||||
return -1;
|
||||
}
|
||||
if (pivot_root(".", "./old")) {
|
||||
fprintf(stderr, "pivot_root(., ./old) failed: %m\n");
|
||||
return -1;
|
||||
}
|
||||
if (umount("./old")) {
|
||||
fprintf(stderr, "umount(./old) failed: %m\n");
|
||||
return -1;
|
||||
}
|
||||
if (mkdir("proc", 0777) && errno != EEXIST) {
|
||||
fprintf(stderr, "mkdir(proc) failed: %m\n");
|
||||
return -1;
|
||||
}
|
||||
if (mount("proc", "/proc", "proc", MS_MGC_VAL, NULL)) {
|
||||
fprintf(stderr, "mount(/proc) failed: %m\n");
|
||||
return -1;
|
||||
}
|
||||
if (fchdir(dfd)) {
|
||||
fprintf(stderr, "fchdir() failed: %m\n");
|
||||
return -1;
|
||||
}
|
||||
close(dfd);
|
||||
}
|
||||
mkdir("/dev", 0777);
|
||||
mknod("/dev/null", 0777 | S_IFCHR, makedev(1, 3));
|
||||
return 0;
|
||||
}
|
||||
struct ns_exec_args {
|
||||
int argc;
|
||||
char **argv;
|
||||
int status_pipe[2];
|
||||
};
|
||||
|
||||
static void ns_sig_hand(int signo)
|
||||
{
|
||||
int status, len = 0;
|
||||
pid_t pid;
|
||||
char buf[128] = "";
|
||||
|
||||
if (signo == SIGTERM) {
|
||||
sig_received = signo;
|
||||
len = snprintf(buf, sizeof(buf), "Time to stop and check\n");
|
||||
goto write_out;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
pid = waitpid(-1, &status, WNOHANG);
|
||||
if (pid == 0)
|
||||
return;
|
||||
if (pid == -1) {
|
||||
if (errno == ECHILD) {
|
||||
if (sig_received)
|
||||
return;
|
||||
sig_received = signo;
|
||||
len = snprintf(buf, sizeof(buf),
|
||||
"All test processes exited\n");
|
||||
} else {
|
||||
len = snprintf(buf, sizeof(buf),
|
||||
"wait() failed: %m\n");
|
||||
}
|
||||
goto write_out;
|
||||
}
|
||||
if (status)
|
||||
fprintf(stderr, "%d return %d\n", pid, status);
|
||||
}
|
||||
|
||||
return;
|
||||
write_out:
|
||||
/* fprintf can't be used in a sighandler due to glibc locks */
|
||||
write(STDERR_FILENO, buf, MAX(len, sizeof(buf)));
|
||||
}
|
||||
|
||||
#define STATUS_FD 255
|
||||
int ns_exec(void *_arg)
|
||||
{
|
||||
struct ns_exec_args *args = (struct ns_exec_args *) _arg;
|
||||
int ret;
|
||||
|
||||
close(args->status_pipe[0]);
|
||||
|
||||
system("ip link set up dev lo");
|
||||
|
||||
ret = dup2(args->status_pipe[1], STATUS_FD);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "dup2() failed: %m\n");
|
||||
return -1;
|
||||
}
|
||||
close(args->status_pipe[1]);
|
||||
if (prepare_mntns())
|
||||
return -1;
|
||||
|
||||
setenv("ZDTM_EXE", "1", 0);
|
||||
execvp(args->argv[0], args->argv);
|
||||
fprintf(stderr, "exec(%s) failed: %m\n", args->argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ns_init(int argc, char **argv)
|
||||
{
|
||||
struct sigaction sa = {
|
||||
.sa_handler = ns_sig_hand,
|
||||
.sa_flags = SA_RESTART,
|
||||
};
|
||||
int ret, fd, status_pipe = STATUS_FD;
|
||||
char buf[128];
|
||||
pid_t pid;
|
||||
|
||||
ret = fcntl(status_pipe, F_SETFD, FD_CLOEXEC);
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "fcntl failed %m\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaddset(&sa.sa_mask, SIGTERM);
|
||||
sigaddset(&sa.sa_mask, SIGCHLD);
|
||||
|
||||
if (sigaction(SIGTERM, &sa, NULL)) {
|
||||
fprintf(stderr, "Can't set SIGTERM handler: %m\n");
|
||||
exit(1);
|
||||
}
|
||||
if (sigaction(SIGCHLD, &sa, NULL)) {
|
||||
fprintf(stderr, "Can't set SIGCHLD handler: %m\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Start test */
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
fprintf(stderr, "fork() failed: %m\n");
|
||||
exit(1);
|
||||
} else if (pid == 0) {
|
||||
ret = execvp(argv[0], argv);
|
||||
fprintf(stderr, "exec(%s) failed: %m\n", argv[0]);
|
||||
return ret;
|
||||
}
|
||||
ret = 1;
|
||||
waitpid(pid, &ret, 0);
|
||||
|
||||
/* Daemonize */
|
||||
write(status_pipe, &ret, sizeof(ret));
|
||||
close(status_pipe);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* suspend/resume */
|
||||
test_waitsig();
|
||||
|
||||
parseargs(argc, argv);
|
||||
|
||||
fd = open(pidfile, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "open(%s) failed: %m\n", pidfile);
|
||||
exit(1);
|
||||
}
|
||||
ret = read(fd, buf, sizeof(buf) - 1);
|
||||
buf[ret] = '\0';
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "read() failed: %m\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pid = atoi(buf);
|
||||
fprintf(stderr, "kill(%d, SIGTERM)\n", pid);
|
||||
if (pid > 0)
|
||||
kill(pid, SIGTERM);
|
||||
|
||||
ret = 0;
|
||||
while (ret != -1)
|
||||
ret = wait(NULL);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#define STACK_SIZE (8 * 4096)
|
||||
void ns_create(int argc, char **argv)
|
||||
{
|
||||
void *stack;
|
||||
pid_t pid;
|
||||
int ret, status;
|
||||
static struct ns_exec_args args;
|
||||
int fd;
|
||||
|
||||
args.argc = argc;
|
||||
args.argv = argv;
|
||||
|
||||
stack = mmap(NULL, STACK_SIZE, PROT_WRITE | PROT_READ,
|
||||
MAP_PRIVATE | MAP_GROWSDOWN | MAP_ANONYMOUS, -1, 0);
|
||||
if (stack == MAP_FAILED) {
|
||||
fprintf(stderr, "Can't map stack %m\n");
|
||||
exit(1);
|
||||
}
|
||||
ret = pipe(args.status_pipe);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Pipe() failed %m\n");
|
||||
exit(1);
|
||||
}
|
||||
pid = clone(ns_exec, stack + STACK_SIZE,
|
||||
CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWUTS |
|
||||
CLONE_NEWNET | CLONE_NEWIPC | SIGCHLD, &args);
|
||||
if (pid < 0) {
|
||||
fprintf(stderr, "clone() failed: %m\n");
|
||||
exit(1);
|
||||
}
|
||||
close(args.status_pipe[1]);
|
||||
|
||||
status = 1;
|
||||
ret = read(args.status_pipe[0], &status, sizeof(status));
|
||||
if (ret != sizeof(status) || status)
|
||||
exit(1);
|
||||
ret = read(args.status_pipe[0], &status, sizeof(status));
|
||||
if (ret != 0)
|
||||
exit(1);
|
||||
|
||||
pidfile = getenv("ZDTM_PIDFILE");
|
||||
if (pidfile == NULL)
|
||||
exit(1);
|
||||
fd = open(pidfile, O_CREAT | O_EXCL | O_WRONLY, 0666);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "Can't create the file %s: %m\n", pidfile);
|
||||
exit(1);
|
||||
}
|
||||
if (dprintf(fd, "%d", pid) == -1) {
|
||||
fprintf(stderr, "Can't write in the file %s: %m\n", pidfile);
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
13
test/zdtm/lib/ns.h
Normal file
13
test/zdtm/lib/ns.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef __ZDTM_NS__
|
||||
#define __ZDTM_NS__
|
||||
|
||||
extern volatile sig_atomic_t sig_received;
|
||||
extern char *pidfile;
|
||||
|
||||
extern void ns_create(int argc, char **argv);
|
||||
extern int ns_init(int argc, char **argv);
|
||||
|
||||
extern void test_waitsig(void);
|
||||
extern void parseargs(int, char **);
|
||||
|
||||
#endif
|
||||
|
|
@ -10,10 +10,14 @@
|
|||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sched.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "zdtmtst.h"
|
||||
#include "ns.h"
|
||||
|
||||
static volatile sig_atomic_t sig_received = 0;
|
||||
volatile sig_atomic_t sig_received = 0;
|
||||
|
||||
static void sig_hand(int signo)
|
||||
{
|
||||
|
|
@ -22,7 +26,7 @@ static void sig_hand(int signo)
|
|||
|
||||
static char *outfile;
|
||||
TEST_OPTION(outfile, string, "output file", 1);
|
||||
static char *pidfile;
|
||||
char *pidfile;
|
||||
TEST_OPTION(pidfile, string, "file to store pid", 1);
|
||||
|
||||
static pid_t master_pid = 0;
|
||||
|
|
@ -85,12 +89,27 @@ void test_init(int argc, char **argv)
|
|||
|
||||
pid_t pid;
|
||||
static FILE *pidf;
|
||||
char *val;
|
||||
struct sigaction sa = {
|
||||
.sa_handler = sig_hand,
|
||||
.sa_flags = SA_RESTART,
|
||||
};
|
||||
sigemptyset(&sa.sa_mask);
|
||||
|
||||
val = getenv("ZDTM_NEWNS");
|
||||
if (val) {
|
||||
unsetenv("ZDTM_NEWNS");
|
||||
ns_create(argc, argv);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
val = getenv("ZDTM_EXE");
|
||||
if (val) {
|
||||
unsetenv("ZDTM_EXE");
|
||||
ns_init(argc, argv);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sigaction(SIGTERM, &sa, NULL)) {
|
||||
fprintf(stderr, "Can't set SIGTERM handler: %m\n");
|
||||
exit(1);
|
||||
|
|
|
|||
|
|
@ -1,245 +0,0 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <sched.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <linux/limits.h>
|
||||
#include <string.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define STACK_SIZE (8 * 4096)
|
||||
#ifndef CLONE_NEWPID
|
||||
/* CLONE_NEWPID since Linux 2.6.24 */
|
||||
#define CLONE_NEWPID 0x20000000
|
||||
#endif
|
||||
|
||||
static int sig_received;
|
||||
static char dir[PATH_MAX];
|
||||
static char name[PATH_MAX];
|
||||
static char pidfile[PATH_MAX];
|
||||
int status_pipe[2];
|
||||
|
||||
static void sig_hand(int signo)
|
||||
{
|
||||
int status, len = 0;
|
||||
pid_t pid;
|
||||
char buf[128] = "";
|
||||
|
||||
if (signo == SIGTERM) {
|
||||
sig_received = signo;
|
||||
len = snprintf(buf, sizeof(buf), "Time to stop and check\n");
|
||||
goto write_out;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
pid = waitpid(-1, &status, WNOHANG);
|
||||
if (pid == 0)
|
||||
return;
|
||||
if (pid == -1) {
|
||||
if (errno == ECHILD) {
|
||||
if (sig_received)
|
||||
return;
|
||||
sig_received = signo;
|
||||
len = snprintf(buf, sizeof(buf),
|
||||
"All test processes exited\n");
|
||||
} else {
|
||||
len = snprintf(buf, sizeof(buf),
|
||||
"wait() failed: %m\n");
|
||||
}
|
||||
goto write_out;
|
||||
}
|
||||
if (status)
|
||||
fprintf(stderr, "%d return %d\n", pid, status);
|
||||
}
|
||||
|
||||
return;
|
||||
write_out:
|
||||
/* fprintf can't be used in a sighandler due to glibc locks */
|
||||
write(STDERR_FILENO, buf, MAX(len, sizeof(buf)));
|
||||
}
|
||||
|
||||
void test_waitsig(void)
|
||||
{
|
||||
sigset_t mask, oldmask;
|
||||
|
||||
/* Set up the mask of signals to temporarily block. */
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGTERM);
|
||||
sigaddset(&mask, SIGCHLD);
|
||||
|
||||
/* Wait for a signal to arrive. */
|
||||
sigprocmask(SIG_BLOCK, &mask, &oldmask);
|
||||
while (!sig_received)
|
||||
sigsuspend (&oldmask);
|
||||
sigprocmask (SIG_UNBLOCK, &mask, NULL);
|
||||
|
||||
sig_received = 0;
|
||||
}
|
||||
|
||||
static int prepare_mntns()
|
||||
{
|
||||
FILE *f;
|
||||
unsigned fs_cnt, fs_cnt_last = 0;
|
||||
char buf[1024];
|
||||
|
||||
again:
|
||||
fs_cnt = 0;
|
||||
f = fopen("/proc/self/mountinfo", "r");
|
||||
if (!f) {
|
||||
fprintf(stderr, "Can't open mountinfo");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fgets(buf, sizeof(buf), f) != NULL) {
|
||||
char *mp = buf, *end;
|
||||
|
||||
mp = strchr(mp, ' ') + 1;
|
||||
mp = strchr(mp, ' ') + 1;
|
||||
mp = strchr(mp, ' ') + 1;
|
||||
mp = strchr(mp, ' ') + 1;
|
||||
end = strchr(mp, ' ');
|
||||
*end = '\0';
|
||||
|
||||
if (!strcmp(mp, "/"))
|
||||
continue;
|
||||
if (!strcmp(mp, "/proc"))
|
||||
continue;
|
||||
|
||||
umount(mp);
|
||||
fs_cnt++;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
if (fs_cnt == 0)
|
||||
goto done;
|
||||
|
||||
if (fs_cnt != fs_cnt_last) {
|
||||
fs_cnt_last = fs_cnt;
|
||||
goto again;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Can't umount all the filesystems");
|
||||
return -1;
|
||||
done:
|
||||
mknod("/dev/null", 0777 | S_IFCHR, makedev(1, 3));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fn(void *_arg)
|
||||
{
|
||||
struct sigaction sa = {
|
||||
.sa_handler = sig_hand,
|
||||
.sa_flags = SA_RESTART,
|
||||
};
|
||||
char cmd[256];
|
||||
int ret;
|
||||
|
||||
close(status_pipe[0]);
|
||||
|
||||
if (prepare_mntns())
|
||||
return 1;
|
||||
|
||||
ret = fcntl(status_pipe[1], F_SETFD, FD_CLOEXEC);
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "fcntl failed %m\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaddset(&sa.sa_mask, SIGTERM);
|
||||
sigaddset(&sa.sa_mask, SIGCHLD);
|
||||
|
||||
if (sigaction(SIGTERM, &sa, NULL)) {
|
||||
fprintf(stderr, "Can't set SIGTERM handler: %m\n");
|
||||
exit(1);
|
||||
}
|
||||
if (sigaction(SIGCHLD, &sa, NULL)) {
|
||||
fprintf(stderr, "Can't set SIGCHLD handler: %m\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Start test */
|
||||
snprintf(cmd, sizeof(cmd), "make -C %s %s.pid", dir, name);
|
||||
ret = system(cmd);
|
||||
|
||||
/* Daemonize */
|
||||
write(status_pipe[1], &ret, sizeof(ret));
|
||||
close(status_pipe[1]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* suspend/resume */
|
||||
test_waitsig();
|
||||
|
||||
/* Stop test */
|
||||
snprintf(cmd, sizeof(cmd), "make -C %s %s.out", dir, name);
|
||||
ret = system(cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = 0;
|
||||
while (ret != -1)
|
||||
ret = wait(NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
void *stack;
|
||||
pid_t pid;
|
||||
int ret, status, fd;
|
||||
|
||||
if (argc < 4)
|
||||
exit(1);
|
||||
|
||||
strcpy(dir, argv[1]);
|
||||
strcpy(name, argv[2]);
|
||||
strcpy(pidfile, argv[3]);
|
||||
|
||||
stack = mmap(NULL, STACK_SIZE, PROT_WRITE | PROT_READ,
|
||||
MAP_PRIVATE | MAP_GROWSDOWN | MAP_ANONYMOUS, -1, 0);
|
||||
if (stack == MAP_FAILED) {
|
||||
fprintf(stderr, "Can't map stack %m\n");
|
||||
exit(1);
|
||||
}
|
||||
ret = pipe(status_pipe);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Pipe() failed %m\n");
|
||||
exit(1);
|
||||
}
|
||||
pid = clone(fn, stack + STACK_SIZE, CLONE_NEWPID | CLONE_NEWNS | SIGCHLD, NULL);
|
||||
if (pid < 0) {
|
||||
fprintf(stderr, "clone() failed: %m\n");
|
||||
exit(1);
|
||||
}
|
||||
close(status_pipe[1]);
|
||||
|
||||
status = 1;
|
||||
ret = read(status_pipe[0], &status, sizeof(status));
|
||||
if (ret != sizeof(status) || status)
|
||||
exit(1);
|
||||
|
||||
fd = open(pidfile, O_CREAT | O_EXCL | O_WRONLY, 0666);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "Can't create a pid file %s: %m", pidfile);
|
||||
return 1;
|
||||
}
|
||||
ret = dprintf(fd, "%d", pid);
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "Can't write in a pid file\n");
|
||||
return 1;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
LIBDIR = ../../lib
|
||||
LIB = $(LIBDIR)/libzdtmtst.a
|
||||
override CPPFLAGS += -I$(LIBDIR)
|
||||
CFLAGS = -g -O2 -Wall -Werror -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
|
||||
CFLAGS = --static -g -O2 -Wall -Werror -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
|
||||
|
||||
TST_NOFILE = \
|
||||
busyloop00 \
|
||||
|
|
@ -173,9 +173,9 @@ futex: override LDFLAGS += -pthread
|
|||
futex-rl.o: override CFLAGS += -pthread
|
||||
futex-rl: override LDFLAGS += -pthread
|
||||
jobctl00: override LDLIBS += -lutil
|
||||
socket_listen: override LDLIBS += -lrt
|
||||
socket_aio: override LDLIBS += -lrt
|
||||
uptime_grow: override LDLIBS += -lrt
|
||||
socket_listen: override LDLIBS += -lrt -pthread
|
||||
socket_aio: override LDLIBS += -lrt -pthread
|
||||
uptime_grow: override LDLIBS += -lrt -pthread
|
||||
unlink_largefile: override CFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
|
||||
inotify_system_nodel: override CFLAGS += -DNODEL
|
||||
pthread00: override LDLIBS += -pthread
|
||||
|
|
|
|||
|
|
@ -35,8 +35,6 @@ int main (int argc, char *argv[])
|
|||
|
||||
wd = 0;
|
||||
wd |= inotify_add_watch(fd, "/", IN_ALL_EVENTS);
|
||||
wd |= inotify_add_watch(fd, "/root", IN_ALL_EVENTS);
|
||||
wd |= inotify_add_watch(fd, "/boot", IN_ALL_EVENTS);
|
||||
if (wd < 0) {
|
||||
fail("inotify_add_watch failed");
|
||||
exit(1);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
LIBDIR = ../../lib
|
||||
LIB = $(LIBDIR)/libzdtmtst.a
|
||||
override CPPFLAGS += -I$(LIBDIR)
|
||||
CFLAGS = -g -O2 -Wall -Werror -fno-strict-aliasing
|
||||
CFLAGS = --static -g -O2 -Wall -Werror -fno-strict-aliasing
|
||||
|
||||
TST_NOFILE = \
|
||||
pipe_loop00 \
|
||||
|
|
@ -57,7 +57,7 @@ wait_stop:
|
|||
|
||||
$(TST): $(LIB)
|
||||
|
||||
file_aio: override LDLIBS += -lrt
|
||||
file_aio: override LDLIBS += -lrt -pthread
|
||||
|
||||
$(LIB): force
|
||||
$(MAKE) -C $(LIBDIR)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
LIBDIR = ../../lib
|
||||
LIB = $(LIBDIR)/libzdtmtst.a
|
||||
override CPPFLAGS += -I$(LIBDIR)
|
||||
CFLAGS = -g -O2 -Wall -Werror
|
||||
CFLAGS = --static -g -O2 -Wall -Werror
|
||||
|
||||
TST_NOFILE = \
|
||||
file_read \
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue