[CRIU] [PATCH 01/13] zdtm: add a test case for pending signals

Andrey Vagin avagin at openvz.org
Fri Mar 15 09:49:12 EDT 2013


Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 test/zdtm/live/static/Makefile     |   3 +
 test/zdtm/live/static/sigpending.c | 232 +++++++++++++++++++++++++++++++++++++
 2 files changed, 235 insertions(+)
 create mode 100644 test/zdtm/live/static/sigpending.c

diff --git a/test/zdtm/live/static/Makefile b/test/zdtm/live/static/Makefile
index f72bb52..9985f2b 100644
--- a/test/zdtm/live/static/Makefile
+++ b/test/zdtm/live/static/Makefile
@@ -88,6 +88,7 @@ TST_NOFILE	=				\
 		cow00				\
 		child_opened_proc		\
 		posix_timers			\
+		sigpending			\
 #		jobctl00			\
 
 TST_FILE	=				\
@@ -219,6 +220,7 @@ unlink_largefile:	override CFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURC
 inotify_system_nodel:	override CFLAGS += -DNODEL
 pthread00:		override LDLIBS += -pthread
 pthread01:		override LDLIBS += -pthread
+sigpending:		override LDLIBS += -pthread
 shm:			override CFLAGS += -DNEW_IPC_NS
 msgque:			override CFLAGS += -DNEW_IPC_NS
 sem:			override CFLAGS += -DNEW_IPC_NS
@@ -226,6 +228,7 @@ posix_timers:		override LDLIBS += -lrt
 socket-tcp6: override CFLAGS += -D ZDTM_IPV6
 socket-tcpbuf6: override CFLAGS += -D ZDTM_IPV6
 socket_listen6: override CFLAGS += -D ZDTM_IPV6
+sigpending:		override LDLIBS += -lrt
 
 $(LIB):	force
 	$(MAKE) -C $(LIBDIR)
diff --git a/test/zdtm/live/static/sigpending.c b/test/zdtm/live/static/sigpending.c
new file mode 100644
index 0000000..040c39b
--- /dev/null
+++ b/test/zdtm/live/static/sigpending.c
@@ -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 at 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;
+}
-- 
1.7.11.7



More information about the CRIU mailing list