mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-19 09:35:12 +00:00
Acked-by: Mike Rapoport <rppt@linux.ibm.com> Signed-off-by: Adrian Reber <areber@redhat.com>
236 lines
5.4 KiB
C
236 lines
5.4 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
#include <signal.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/mman.h>
|
|
#include <fcntl.h>
|
|
#include <pthread.h>
|
|
|
|
#include "zdtmtst.h"
|
|
|
|
#define gettid() pthread_self()
|
|
|
|
const char *test_doc = "Create a few pthreads and test TLS + blocked signals\n";
|
|
const char *test_author = "Cyrill Gorcunov <gorcunov@openvz.org";
|
|
|
|
static __thread struct tls_data_s {
|
|
char *rand_string[10];
|
|
sigset_t blk_sigset;
|
|
} tls_data;
|
|
|
|
static task_waiter_t t1;
|
|
static task_waiter_t t2;
|
|
|
|
#ifdef CONFIG_MIPS
|
|
#ifndef SIGSTKFLT
|
|
#define SIGSTKFLT 16
|
|
#endif
|
|
#endif
|
|
static char *decode_signal(const sigset_t *s, char *buf)
|
|
{
|
|
buf[0] = '\0';
|
|
|
|
#define COLLECT(sig) \
|
|
do { \
|
|
if (sigismember(s, sig)) \
|
|
strcat(buf, #sig " "); \
|
|
} while (0)
|
|
|
|
COLLECT(SIGHUP);
|
|
COLLECT(SIGINT);
|
|
COLLECT(SIGQUIT);
|
|
COLLECT(SIGILL);
|
|
COLLECT(SIGTRAP);
|
|
COLLECT(SIGABRT);
|
|
COLLECT(SIGIOT);
|
|
COLLECT(SIGBUS);
|
|
COLLECT(SIGFPE);
|
|
COLLECT(SIGKILL);
|
|
COLLECT(SIGUSR1);
|
|
COLLECT(SIGSEGV);
|
|
COLLECT(SIGUSR2);
|
|
COLLECT(SIGPIPE);
|
|
COLLECT(SIGALRM);
|
|
COLLECT(SIGTERM);
|
|
COLLECT(SIGSTKFLT);
|
|
COLLECT(SIGCHLD);
|
|
COLLECT(SIGCONT);
|
|
COLLECT(SIGSTOP);
|
|
COLLECT(SIGTSTP);
|
|
COLLECT(SIGTTIN);
|
|
COLLECT(SIGTTOU);
|
|
COLLECT(SIGURG);
|
|
COLLECT(SIGXCPU);
|
|
COLLECT(SIGXFSZ);
|
|
COLLECT(SIGVTALRM);
|
|
COLLECT(SIGPROF);
|
|
COLLECT(SIGWINCH);
|
|
COLLECT(SIGIO);
|
|
COLLECT(SIGPOLL);
|
|
COLLECT(SIGPWR);
|
|
COLLECT(SIGSYS);
|
|
#undef COLLECT
|
|
|
|
return buf;
|
|
}
|
|
|
|
static void __show_sigset(int line, const sigset_t *s)
|
|
{
|
|
char buf[sizeof(sigset_t) * 2 + 1] = {};
|
|
|
|
decode_signal(s, buf);
|
|
test_msg("sigset at %4d: %s\n", line, buf);
|
|
}
|
|
|
|
#define show_sigset(set) __show_sigset(__LINE__, set)
|
|
|
|
static void *ch_thread_2(void *arg)
|
|
{
|
|
char __tls_data[sizeof(tls_data.rand_string)] = "XM5o:?B*[a";
|
|
int *results_map = arg;
|
|
sigset_t blk_sigset = {};
|
|
sigset_t new = {};
|
|
|
|
memcpy(tls_data.rand_string, __tls_data, sizeof(tls_data.rand_string));
|
|
|
|
sigemptyset(&blk_sigset);
|
|
pthread_sigmask(SIG_SETMASK, NULL, &blk_sigset);
|
|
sigaddset(&blk_sigset, SIGFPE);
|
|
pthread_sigmask(SIG_SETMASK, &blk_sigset, NULL);
|
|
memcpy(&tls_data.blk_sigset, &blk_sigset, sizeof(tls_data.blk_sigset));
|
|
|
|
show_sigset(&blk_sigset);
|
|
show_sigset(&tls_data.blk_sigset);
|
|
|
|
task_waiter_complete(&t2, 1);
|
|
task_waiter_wait4(&t2, 2);
|
|
|
|
if (memcmp(tls_data.rand_string, __tls_data, sizeof(tls_data.rand_string))) {
|
|
pr_perror("Failed to restore tls_data.rand_string in thread 2");
|
|
results_map[2] = -1;
|
|
} else
|
|
results_map[2] = 1;
|
|
|
|
if (memcmp(&tls_data.blk_sigset, &blk_sigset, sizeof(tls_data.blk_sigset))) {
|
|
pr_perror("Failed to restore tls_data.blk_sigset in thread 2");
|
|
results_map[4] = -1;
|
|
} else
|
|
results_map[4] = 1;
|
|
|
|
pthread_sigmask(SIG_SETMASK, NULL, &new);
|
|
if (memcmp(&tls_data.blk_sigset, &new, sizeof(tls_data.blk_sigset))) {
|
|
pr_perror("Failed to restore blk_sigset in thread 2");
|
|
results_map[6] = -1;
|
|
|
|
show_sigset(&tls_data.blk_sigset);
|
|
show_sigset(&new);
|
|
} else
|
|
results_map[6] = 1;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void *ch_thread_1(void *arg)
|
|
{
|
|
char __tls_data[sizeof(tls_data.rand_string)] = "pffYQSBo?6";
|
|
int *results_map = arg;
|
|
sigset_t blk_sigset = {};
|
|
sigset_t new = {};
|
|
|
|
memcpy(tls_data.rand_string, __tls_data, sizeof(tls_data.rand_string));
|
|
|
|
sigemptyset(&blk_sigset);
|
|
pthread_sigmask(SIG_SETMASK, NULL, &blk_sigset);
|
|
sigaddset(&blk_sigset, SIGWINCH);
|
|
sigaddset(&blk_sigset, SIGALRM);
|
|
pthread_sigmask(SIG_SETMASK, &blk_sigset, NULL);
|
|
memcpy(&tls_data.blk_sigset, &blk_sigset, sizeof(tls_data.blk_sigset));
|
|
|
|
show_sigset(&blk_sigset);
|
|
show_sigset(&tls_data.blk_sigset);
|
|
|
|
task_waiter_complete(&t1, 1);
|
|
task_waiter_wait4(&t1, 2);
|
|
|
|
if (memcmp(tls_data.rand_string, __tls_data, sizeof(tls_data.rand_string))) {
|
|
pr_perror("Failed to restore tls_data.rand_string in thread 1");
|
|
results_map[1] = -1;
|
|
} else
|
|
results_map[1] = 1;
|
|
|
|
if (memcmp(&tls_data.blk_sigset, &blk_sigset, sizeof(tls_data.blk_sigset))) {
|
|
pr_perror("Failed to restore tls_data.blk_sigset in thread 1");
|
|
results_map[3] = -1;
|
|
} else
|
|
results_map[3] = 1;
|
|
|
|
sigemptyset(&new);
|
|
pthread_sigmask(SIG_SETMASK, NULL, &new);
|
|
if (memcmp(&tls_data.blk_sigset, &new, sizeof(tls_data.blk_sigset))) {
|
|
pr_perror("Failed to restore blk_sigset in thread 1");
|
|
results_map[5] = -1;
|
|
|
|
show_sigset(&tls_data.blk_sigset);
|
|
show_sigset(&new);
|
|
} else
|
|
results_map[5] = 1;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
pthread_t thread_1, thread_2;
|
|
int *results_map;
|
|
int rc1, rc2;
|
|
|
|
test_init(argc, argv);
|
|
|
|
task_waiter_init(&t1);
|
|
task_waiter_init(&t2);
|
|
|
|
test_msg("%s pid %d\n", argv[0], getpid());
|
|
|
|
results_map = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
|
if ((void *)results_map == MAP_FAILED) {
|
|
fail("Can't map");
|
|
exit(1);
|
|
}
|
|
|
|
rc1 = pthread_create(&thread_1, NULL, &ch_thread_1, results_map);
|
|
rc2 = pthread_create(&thread_2, NULL, &ch_thread_2, results_map);
|
|
|
|
if (rc1 | rc2) {
|
|
fail("Can't pthread_create");
|
|
exit(1);
|
|
}
|
|
|
|
test_msg("Waiting until all threads are created\n");
|
|
|
|
task_waiter_wait4(&t1, 1);
|
|
task_waiter_wait4(&t2, 1);
|
|
|
|
test_daemon();
|
|
test_waitsig();
|
|
|
|
task_waiter_complete(&t1, 2);
|
|
task_waiter_complete(&t2, 2);
|
|
|
|
test_msg("Waiting while all threads are joined\n");
|
|
pthread_join(thread_1, NULL);
|
|
pthread_join(thread_2, NULL);
|
|
|
|
if (results_map[1] == 1 && results_map[2] == 1 && results_map[3] == 1 && results_map[4] == 1 &&
|
|
results_map[5] == 1 && results_map[6] == 1)
|
|
pass();
|
|
else
|
|
fail();
|
|
|
|
return 0;
|
|
}
|