2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-30 22:05:36 +00:00

zdtm: add tests for SIGTSTP

stopped03 check that stopped by SIGTSTP tasks are restored correctly.
stopped04 check that stopped by SIGSTOP tasks which have blocked SIGTSTP and
have SIGTSTP pending are restored correctly.

Signed-off-by: Yuriy Vasiliev <yuriy.vasiliev@openvz.org>
This commit is contained in:
Yuriy Vasiliev
2022-01-18 14:35:55 +01:00
committed by Andrei Vagin
parent c7858ba42b
commit 6cef6e726a
3 changed files with 298 additions and 0 deletions

View File

@@ -184,6 +184,8 @@ TST_NOFILE := \
stopped01 \
stopped02 \
stopped12 \
stopped03 \
stopped04 \
rtc \
clean_mntns \
mntns_rw_ro_rw \

View File

@@ -0,0 +1,161 @@
#include <signal.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include "zdtmtst.h"
#include "lock.h"
const char *test_doc = "Check, that stopped by SIGTSTP tasks are restored correctly";
const char *test_author = "Yuriy Vasiliev <yuriy.vasiliev@openvz.org>";
#define STOP_SIGNO SIGTSTP
const char *stop_sigstr = "SIGTSTP";
enum {
FUTEX_INITIALIZED = 0,
TEST_CRIU,
TEST_CHECK,
TEST_DONE,
TEST_EXIT,
TEST_EMERGENCY_ABORT,
};
struct shared {
futex_t fstate;
int status;
int code;
} * sh;
static int new_pgrp(void)
{
siginfo_t infop;
int ret = 1;
pid_t pid;
/*
* Set the PGID to avoid creating an orphaned process group,
* which is not to be affected by terminal-generated stop signals.
*/
setpgid(0, 0);
pid = test_fork();
if (pid < 0)
goto err_cr;
if (pid == 0) {
/* wait for TEST_EXIT or TEST_EMERGENCY_ABORT*/
futex_wait_while_lt(&sh->fstate, TEST_EXIT);
exit(0);
}
if (kill(pid, STOP_SIGNO)) {
pr_perror("Unable to send %s", stop_sigstr);
goto err_cr;
}
if (waitid(P_PID, pid, &infop, WNOWAIT | WSTOPPED) < 0) {
pr_perror("Unable to waitid %d", pid);
goto err_cont;
}
sh->code = infop.si_code;
sh->status = infop.si_status;
/* Return the control back to MAIN worker to do C/R */
futex_set_and_wake(&sh->fstate, TEST_CRIU);
futex_wait_while_lt(&sh->fstate, TEST_CHECK);
infop.si_code = 0;
infop.si_status = 0;
if (waitid(P_PID, pid, &infop, WNOWAIT | WSTOPPED) < 0) {
pr_perror("Unable to waitid %d", pid);
goto err_cont;
}
sh->code = infop.si_code;
sh->status = infop.si_status;
futex_set_and_wake(&sh->fstate, TEST_DONE);
futex_wait_while_lt(&sh->fstate, TEST_EXIT);
ret = 0;
err_cont:
kill(pid, SIGCONT);
err_cr:
if (ret)
futex_set_and_wake(&sh->fstate, TEST_EMERGENCY_ABORT);
if (pid > 0)
wait(NULL);
return ret;
}
int main(int argc, char **argv)
{
int fail = 0;
pid_t pid;
test_init(argc, argv);
sh = mmap(NULL, sizeof(struct shared), PROT_WRITE | PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (sh == MAP_FAILED) {
pr_perror("Failed to alloc shared region");
return 1;
}
futex_set(&sh->fstate, FUTEX_INITIALIZED);
pid = test_fork();
if (pid < 0) {
fail = 1;
goto out;
}
if (pid == 0)
exit(new_pgrp());
/* Wait until pgrp is ready to C/R */
futex_wait_while_lt(&sh->fstate, TEST_CRIU);
if (futex_get(&sh->fstate) == TEST_EMERGENCY_ABORT) {
pr_err("Fail in child worker before C/R\n");
fail = 1;
goto out;
}
if (sh->code != CLD_STOPPED || sh->status != STOP_SIGNO) {
pr_err("Process is not in correct state before C/R."
" Expected stop signo: %d. Get stop signo: %d\n",
STOP_SIGNO, sh->status);
fail = 1;
goto out;
}
test_daemon();
test_waitsig();
futex_set_and_wake(&sh->fstate, TEST_CHECK);
futex_wait_while_lt(&sh->fstate, TEST_DONE);
if (futex_get(&sh->fstate) == TEST_EMERGENCY_ABORT) {
pr_err("Fail in child worker after C/R\n");
goto out;
}
if (sh->code != CLD_STOPPED || sh->status != STOP_SIGNO) {
fail = 1;
pr_err("Process is not in correct state after C/R."
" Expected stop signo: %d. Get stop signo: %d\n",
STOP_SIGNO, sh->status);
}
if (!fail)
pass();
futex_set_and_wake(&sh->fstate, TEST_EXIT);
out:
if (pid > 0)
wait(NULL);
munmap(sh, sizeof(struct shared));
return fail;
}

View File

@@ -0,0 +1,135 @@
#include <signal.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include "zdtmtst.h"
#include "lock.h"
const char *test_doc = "Check, that stopped by SIGTSTP tasks are restored correctly";
const char *test_author = "Yuriy Vasiliev <yuriy.vasiliev@openvz.org>";
const char *stop_sigstr = "SIGTSTP";
enum {
FUTEX_INITIALIZED = 0,
TEST_CRIU,
TEST_DONE,
TEST_EXIT,
TEST_EMERGENCY_ABORT,
};
struct shared {
futex_t fstate;
int status;
int code;
} * sh;
static int new_pgrp(void)
{
sigset_t sigset;
siginfo_t infop;
int ret = 1;
pid_t pid;
/*
* Set the PGID to avoid creating an orphaned process group,
* which is not to be affected by terminal-generated stop signals.
*/
setpgid(0, 0);
sigemptyset(&sigset);
sigaddset(&sigset, SIGTSTP);
sigprocmask(SIG_BLOCK, &sigset, NULL);
pid = test_fork();
if (pid < 0)
goto err_cr;
if (pid == 0) {
/* wait for TEST_EXIT or TEST_EMERGENCY_ABORT*/
futex_wait_while_lt(&sh->fstate, TEST_EXIT);
exit(0);
}
if (kill(pid, SIGSTOP)) {
pr_perror("Unable to send %s", stop_sigstr);
goto err_cr;
}
if (waitid(P_PID, pid, &infop, WNOWAIT | WSTOPPED) < 0) {
pr_perror("Unable to waitid %d", pid);
goto err_cont;
}
if (kill(pid, SIGTSTP)) {
pr_perror("Unable to send %s", stop_sigstr);
goto err_cr;
}
/* Return the control back to MAIN worker to do C/R */
futex_set_and_wake(&sh->fstate, TEST_CRIU);
futex_wait_while_lt(&sh->fstate, TEST_EXIT);
ret = 0;
err_cont:
kill(pid, SIGCONT);
err_cr:
if (ret)
futex_set_and_wake(&sh->fstate, TEST_EMERGENCY_ABORT);
if (pid > 0)
wait(NULL);
return ret;
}
int main(int argc, char **argv)
{
int fail = 0;
pid_t pid;
test_init(argc, argv);
sh = mmap(NULL, sizeof(struct shared), PROT_WRITE | PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (sh == MAP_FAILED) {
pr_perror("Failed to alloc shared region");
return 1;
}
futex_set(&sh->fstate, FUTEX_INITIALIZED);
pid = test_fork();
if (pid < 0) {
fail = 1;
goto out;
}
if (pid == 0)
exit(new_pgrp());
/* Wait until pgrp is ready to C/R */
futex_wait_while_lt(&sh->fstate, TEST_CRIU);
if (futex_get(&sh->fstate) == TEST_EMERGENCY_ABORT) {
pr_err("Fail in child worker before C/R\n");
fail = 1;
goto out;
}
test_daemon();
test_waitsig();
if (futex_get(&sh->fstate) == TEST_EMERGENCY_ABORT) {
pr_err("Fail in child worker after C/R\n");
goto out;
}
if (!fail)
pass();
futex_set_and_wake(&sh->fstate, TEST_EXIT);
out:
if (pid > 0)
wait(NULL);
munmap(sh, sizeof(struct shared));
return fail;
}