[PATCH] test: zdtm -- Add test for alternative signal stack

Cyrill Gorcunov gorcunov at openvz.org
Mon Jun 17 03:39:33 EDT 2013


Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 test/zdtm.sh                        |   1 +
 test/zdtm/live/static/Makefile      |   2 +
 test/zdtm/live/static/sigaltstack.c | 168 ++++++++++++++++++++++++++++++++++++
 3 files changed, 171 insertions(+)
 create mode 100644 test/zdtm/live/static/sigaltstack.c

diff --git a/test/zdtm.sh b/test/zdtm.sh
index fd807e9..2d821fd 100755
--- a/test/zdtm.sh
+++ b/test/zdtm.sh
@@ -86,6 +86,7 @@ static/fdt_shared
 static/file_locks00
 static/file_locks01
 static/sigpending
+static/sigaltstack
 static/sk-netlink
 static/proc-self
 "
diff --git a/test/zdtm/live/static/Makefile b/test/zdtm/live/static/Makefile
index 0432030..e4b5e25 100644
--- a/test/zdtm/live/static/Makefile
+++ b/test/zdtm/live/static/Makefile
@@ -94,6 +94,7 @@ TST_NOFILE	=				\
 		child_opened_proc		\
 		posix_timers			\
 		sigpending			\
+		sigaltstack			\
 		sk-netlink			\
 		mem-touch			\
 #		jobctl00			\
@@ -228,6 +229,7 @@ inotify_system_nodel:	override CFLAGS += -DNODEL
 pthread00:		override LDLIBS += -pthread
 pthread01:		override LDLIBS += -pthread
 sigpending:		override LDLIBS += -pthread
+sigaltstack:		override LDLIBS += -pthread
 shm:			override CFLAGS += -DNEW_IPC_NS
 msgque:			override CFLAGS += -DNEW_IPC_NS
 sem:			override CFLAGS += -DNEW_IPC_NS
diff --git a/test/zdtm/live/static/sigaltstack.c b/test/zdtm/live/static/sigaltstack.c
new file mode 100644
index 0000000..b84c3d6
--- /dev/null
+++ b/test/zdtm/live/static/sigaltstack.c
@@ -0,0 +1,168 @@
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <string.h>
+#include <pthread.h>
+#include <syscall.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "zdtmtst.h"
+
+const char *test_doc	= "Check for alternate signal stack";
+const char *test_author	= "Cyrill Gorcunov <gorcunov at openvz.org>";
+
+static char stack_thread[SIGSTKSZ];
+static char stack_main[SIGSTKSZ];
+
+enum {
+	SAS_MAIN_OLD,
+	SAS_MAIN_NEW,
+	SAS_THRD_OLD,
+	SAS_THRD_NEW,
+
+	SAS_MAX
+};
+static stack_t sas_state[SAS_MAX];
+
+static task_waiter_t t;
+
+#define exit_group(code)	syscall(__NR_exit_group, code)
+#define gettid()		syscall(__NR_gettid)
+
+static int sascmp(stack_t *old, stack_t *new)
+{
+	return old->ss_size != new->ss_size	||
+		old->ss_sp != new->ss_sp	||
+		old->ss_flags != new->ss_flags;
+}
+
+static void show_ss(char *prefix, stack_t *s)
+{
+	test_msg("%20s: at %p (size %#8x flags %#2x)\n",
+		 prefix, s->ss_sp, s->ss_size, s->ss_flags);
+}
+
+void thread_sigaction(int signo, siginfo_t *info, void *context)
+{
+	if (sigaltstack(NULL, &sas_state[SAS_THRD_NEW]))
+		err("thread sigaltstack");
+
+	show_ss("thread in sas", &sas_state[SAS_THRD_NEW]);
+
+	task_waiter_complete(&t, 2);
+
+	test_msg("Waiting in thread SAS\n");
+	task_waiter_wait4(&t, 3);
+	test_msg("Leaving thread SAS\n");
+}
+
+static void *thread_func(void *arg)
+{
+	sas_state[SAS_THRD_OLD] = (stack_t) {
+		.ss_size	= SIGSTKSZ,
+		.ss_sp		= stack_thread,
+		.ss_flags	= SS_ONSTACK,
+	};
+
+	struct sigaction sa = {
+		.sa_sigaction	= thread_sigaction,
+		.sa_flags	= SA_RESTART | SA_ONSTACK,
+	};
+
+	sigemptyset(&sa.sa_mask);
+
+	if (sigaction(SIGUSR2, &sa, NULL)) {
+		err("Can't set SIGUSR2 handler");
+		exit_group(-1);
+	}
+
+	task_waiter_wait4(&t, 1);
+
+	if (sigaltstack(&sas_state[SAS_THRD_OLD], NULL)) {
+		err("thread sigaltstack");
+		exit_group(-1);
+	}
+
+	kill(gettid(), SIGUSR2);
+
+	return NULL;
+}
+
+void leader_sigaction(int signo, siginfo_t *info, void *context)
+{
+	if (sigaltstack(NULL, &sas_state[SAS_MAIN_NEW]))
+		err("leader sigaltstack");
+
+	show_ss("leader in sas", &sas_state[SAS_MAIN_NEW]);
+}
+
+int main(int argc, char *argv[])
+{
+	pthread_t thread;
+
+	sas_state[SAS_MAIN_OLD] = (stack_t) {
+		.ss_size	= SIGSTKSZ,
+		.ss_sp		= stack_main,
+		.ss_flags	= SS_ONSTACK,
+	};
+
+	struct sigaction sa = {
+		.sa_sigaction	= leader_sigaction,
+		.sa_flags	= SA_RESTART | SA_ONSTACK,
+	};
+
+	sigemptyset(&sa.sa_mask);
+
+	test_init(argc, argv);
+	task_waiter_init(&t);
+
+	if (sigaction(SIGUSR1, &sa, NULL)) {
+		err("Can't set SIGUSR1 handler");
+		exit(-1);
+	}
+
+	if (pthread_create(&thread, NULL, &thread_func, NULL)) {
+		err("Can't create thread");
+		exit(-1);
+	}
+
+	if (sigaltstack(&sas_state[SAS_MAIN_OLD], NULL)) {
+		err("sigaltstack");
+		exit(-1);
+	}
+
+	task_waiter_complete(&t, 1);
+	task_waiter_wait4(&t, 2);
+
+	test_daemon();
+	test_waitsig();
+
+	test_msg("Thread may leave SAS\n");
+	task_waiter_complete(&t, 3);
+
+	kill(gettid(), SIGUSR1);
+
+	if (pthread_join(thread, NULL)) {
+		fail("Error joining thread");
+		exit(-1);
+	}
+	task_waiter_fini(&t);
+
+	show_ss("main old", &sas_state[SAS_MAIN_OLD]);
+	show_ss("main new", &sas_state[SAS_MAIN_NEW]);
+	show_ss("thrd old", &sas_state[SAS_THRD_OLD]);
+	show_ss("thrd new", &sas_state[SAS_THRD_NEW]);
+
+	if (sascmp(&sas_state[SAS_MAIN_OLD], &sas_state[SAS_MAIN_NEW]) ||
+	    sascmp(&sas_state[SAS_THRD_OLD], &sas_state[SAS_THRD_NEW])) {
+		fail("sas not restored");
+	} else
+		pass();
+
+	return 0;
+}
-- 
1.8.1.4


--pWyiEgJYm5f9v55/--


More information about the CRIU mailing list