mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-28 12:57:57 +00:00
zdtm: add a test case for pending signals
Signed-off-by: Andrey Vagin <avagin@openvz.org> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
parent
be2773660b
commit
13e9291b51
@ -89,6 +89,7 @@ TST_NOFILE = \
|
|||||||
cow00 \
|
cow00 \
|
||||||
child_opened_proc \
|
child_opened_proc \
|
||||||
posix_timers \
|
posix_timers \
|
||||||
|
sigpending \
|
||||||
# jobctl00 \
|
# jobctl00 \
|
||||||
|
|
||||||
TST_FILE = \
|
TST_FILE = \
|
||||||
@ -220,6 +221,7 @@ unlink_largefile: override CFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURC
|
|||||||
inotify_system_nodel: override CFLAGS += -DNODEL
|
inotify_system_nodel: override CFLAGS += -DNODEL
|
||||||
pthread00: override LDLIBS += -pthread
|
pthread00: override LDLIBS += -pthread
|
||||||
pthread01: override LDLIBS += -pthread
|
pthread01: override LDLIBS += -pthread
|
||||||
|
sigpending: override LDLIBS += -pthread
|
||||||
shm: override CFLAGS += -DNEW_IPC_NS
|
shm: override CFLAGS += -DNEW_IPC_NS
|
||||||
msgque: override CFLAGS += -DNEW_IPC_NS
|
msgque: override CFLAGS += -DNEW_IPC_NS
|
||||||
sem: override CFLAGS += -DNEW_IPC_NS
|
sem: override CFLAGS += -DNEW_IPC_NS
|
||||||
@ -227,6 +229,7 @@ posix_timers: override LDLIBS += -lrt
|
|||||||
socket-tcp6: override CFLAGS += -D ZDTM_IPV6
|
socket-tcp6: override CFLAGS += -D ZDTM_IPV6
|
||||||
socket-tcpbuf6: override CFLAGS += -D ZDTM_IPV6
|
socket-tcpbuf6: override CFLAGS += -D ZDTM_IPV6
|
||||||
socket_listen6: override CFLAGS += -D ZDTM_IPV6
|
socket_listen6: override CFLAGS += -D ZDTM_IPV6
|
||||||
|
sigpending: override LDLIBS += -lrt
|
||||||
|
|
||||||
$(LIB): force
|
$(LIB): force
|
||||||
$(MAKE) -C $(LIBDIR)
|
$(MAKE) -C $(LIBDIR)
|
||||||
|
232
test/zdtm/live/static/sigpending.c
Normal file
232
test/zdtm/live/static/sigpending.c
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "zdtmtst.h"
|
||||||
|
|
||||||
|
const char *test_doc = "Check pending signals";
|
||||||
|
const char *test_author = "Andrew Vagin <avagin@parallels.com>";
|
||||||
|
|
||||||
|
static pid_t child;
|
||||||
|
static int numsig;
|
||||||
|
|
||||||
|
#define TESTSIG (SIGRTMAX)
|
||||||
|
#define THREADSIG (SIGRTMIN)
|
||||||
|
static siginfo_t share_infos[2];
|
||||||
|
static siginfo_t self_infos[64]; /* self */
|
||||||
|
static siginfo_t thread_infos[3]; /* thread */
|
||||||
|
static int share_nr;
|
||||||
|
static int self_nr;
|
||||||
|
static int thread_nr;
|
||||||
|
|
||||||
|
#ifndef offsetof
|
||||||
|
# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static pthread_mutex_t exit_lock;
|
||||||
|
static pthread_mutex_t init_lock;
|
||||||
|
|
||||||
|
static void sig_handler(int signal, siginfo_t *info, void *data)
|
||||||
|
{
|
||||||
|
uint32_t crc;
|
||||||
|
|
||||||
|
test_msg("signo=%d si_code=%x\n", signal, info->si_code);
|
||||||
|
|
||||||
|
switch (signal) {
|
||||||
|
case SIGCHLD:
|
||||||
|
if ((info->si_code & CLD_EXITED) &&
|
||||||
|
(info->si_pid == child) &&
|
||||||
|
(info->si_status == 5))
|
||||||
|
numsig++;
|
||||||
|
else {
|
||||||
|
fail("Wrong siginfo");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TESTSIG == signal || THREADSIG == signal) {
|
||||||
|
siginfo_t *src;
|
||||||
|
|
||||||
|
if (signal == TESTSIG) {
|
||||||
|
src = &share_infos[share_nr];
|
||||||
|
share_nr++;
|
||||||
|
} else if (getpid() == syscall(SYS_gettid)) {
|
||||||
|
src = &self_infos[self_nr];
|
||||||
|
self_nr++;
|
||||||
|
} else {
|
||||||
|
src = &thread_infos[thread_nr];
|
||||||
|
thread_nr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
crc = ~0;
|
||||||
|
if (datachk((uint8_t *) &info->_sifields,
|
||||||
|
sizeof(siginfo_t) - offsetof(siginfo_t, _sifields), &crc)) {
|
||||||
|
fail("CRC mismatch\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(info, src, sizeof(siginfo_t))) {
|
||||||
|
fail("Source and received info are differ\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
numsig++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
err("Unexpected signal");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int thread_id;
|
||||||
|
|
||||||
|
static void *thread_fn(void *args)
|
||||||
|
{
|
||||||
|
sigset_t blockmask;
|
||||||
|
struct sigaction act;
|
||||||
|
|
||||||
|
sigfillset(&blockmask);
|
||||||
|
sigdelset(&blockmask, SIGTERM);
|
||||||
|
|
||||||
|
if (sigprocmask(SIG_BLOCK, &blockmask, NULL) == -1) {
|
||||||
|
err("sigprocmask");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_id = syscall(SYS_gettid);
|
||||||
|
|
||||||
|
act.sa_flags = SA_SIGINFO | SA_RESTART;
|
||||||
|
act.sa_sigaction = sig_handler;
|
||||||
|
sigemptyset(&act.sa_mask);
|
||||||
|
|
||||||
|
sigaddset(&act.sa_mask, TESTSIG);
|
||||||
|
sigaddset(&act.sa_mask, THREADSIG);
|
||||||
|
if (sigaction(TESTSIG, &act, NULL)) {
|
||||||
|
err("sigaction() failed\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&init_lock);
|
||||||
|
pthread_mutex_lock(&exit_lock);
|
||||||
|
|
||||||
|
if (sigprocmask(SIG_UNBLOCK, &blockmask, NULL) == -1) {
|
||||||
|
err("sigprocmask");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sent_sigs;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char ** argv)
|
||||||
|
{
|
||||||
|
sigset_t blockmask;
|
||||||
|
struct sigaction act;
|
||||||
|
pthread_t pthrd;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
test_init(argc, argv);
|
||||||
|
pthread_mutex_init(&exit_lock, NULL);
|
||||||
|
pthread_mutex_lock(&exit_lock);
|
||||||
|
pthread_mutex_init(&init_lock, NULL);
|
||||||
|
pthread_mutex_lock(&init_lock);
|
||||||
|
|
||||||
|
if (pthread_create(&pthrd, NULL, thread_fn, NULL)) {
|
||||||
|
err("Can't create a thread");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&init_lock);
|
||||||
|
|
||||||
|
sigfillset(&blockmask);
|
||||||
|
sigdelset(&blockmask, SIGTERM);
|
||||||
|
|
||||||
|
if (sigprocmask(SIG_BLOCK, &blockmask, NULL) == -1) {
|
||||||
|
err("sigprocmask");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
child = fork();
|
||||||
|
if (child == -1) {
|
||||||
|
err("fork");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(child == 0)
|
||||||
|
return 5; /* SIGCHLD */
|
||||||
|
|
||||||
|
sent_sigs++;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(share_infos) / sizeof(siginfo_t); i++) {
|
||||||
|
send_siginfo(TESTSIG, getpid(), -1, 1, share_infos + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(self_infos) / sizeof(siginfo_t); i++) {
|
||||||
|
send_siginfo(THREADSIG, getpid(), getpid(), 0, self_infos + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(thread_infos) / sizeof(siginfo_t); i++) {
|
||||||
|
send_siginfo(THREADSIG, getpid(), thread_id, 0, thread_infos + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
act.sa_flags = SA_SIGINFO | SA_RESTART;
|
||||||
|
act.sa_sigaction = sig_handler;
|
||||||
|
sigemptyset(&act.sa_mask);
|
||||||
|
|
||||||
|
if (sigaction(SIGCHLD, &act, NULL)) {
|
||||||
|
err("sigaction() failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sigaddset(&act.sa_mask, TESTSIG);
|
||||||
|
sigaddset(&act.sa_mask, THREADSIG);
|
||||||
|
if (sigaction(TESTSIG, &act, NULL)) {
|
||||||
|
err("sigaction() failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sigaction(THREADSIG, &act, NULL)) {
|
||||||
|
err("sigaction() failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
test_daemon();
|
||||||
|
|
||||||
|
test_waitsig();
|
||||||
|
|
||||||
|
if (sigprocmask(SIG_UNBLOCK, &blockmask, NULL) == -1) {
|
||||||
|
err("sigprocmask");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&exit_lock);
|
||||||
|
pthread_join(pthrd, NULL);
|
||||||
|
|
||||||
|
if (numsig == sent_sigs)
|
||||||
|
pass();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user