|
@@ -0,0 +1,108 @@
|
|
|
+#include <err.h>
|
|
|
+#include <inttypes.h>
|
|
|
+#include <signal.h>
|
|
|
+#include <stdio.h>
|
|
|
+#include <stdlib.h>
|
|
|
+#include <string.h>
|
|
|
+#include <unistd.h>
|
|
|
+
|
|
|
+uint8_t* sig_stack;
|
|
|
+size_t sig_stack_size = SIGSTKSZ;
|
|
|
+_Atomic int count = 0;
|
|
|
+
|
|
|
+void handler(int signal, siginfo_t* info, void* ucontext) {
|
|
|
+ int ret;
|
|
|
+ count++;
|
|
|
+
|
|
|
+ uint8_t a;
|
|
|
+ printf("sig %d count %d goes off with sp=%p, sig_stack: [%p, %p)\n", signal, count, &a,
|
|
|
+ sig_stack, sig_stack + sig_stack_size);
|
|
|
+ if (sig_stack <= &a && &a < sig_stack + sig_stack_size) {
|
|
|
+ printf("OK on signal stack\n");
|
|
|
+ } else {
|
|
|
+ printf("FAIL out of signal stack\n");
|
|
|
+ }
|
|
|
+ fflush(stdout);
|
|
|
+
|
|
|
+ stack_t old;
|
|
|
+ memset(&old, 0, sizeof(old));
|
|
|
+ ret = sigaltstack(NULL, &old);
|
|
|
+ if (ret < 0) {
|
|
|
+ err(EXIT_FAILURE, "sigaltstack in handler");
|
|
|
+ }
|
|
|
+ if (old.ss_flags & SS_ONSTACK) {
|
|
|
+ printf("OK on sigaltstack in handler\n");
|
|
|
+ } else {
|
|
|
+ printf("FAIL on sigaltstack in handler\n");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * raise SIGALRM during signal handling to test nested signals
|
|
|
+ * (three-levels deep nesting just to be sure)
|
|
|
+ */
|
|
|
+ if (count <= 2) {
|
|
|
+ sigset_t set;
|
|
|
+ sigemptyset(&set);
|
|
|
+ sigaddset(&set, SIGALRM);
|
|
|
+ ret = sigprocmask(SIG_UNBLOCK, &set, NULL);
|
|
|
+ if (ret) {
|
|
|
+ err(EXIT_FAILURE, "sigprocmask");
|
|
|
+ }
|
|
|
+ raise(SIGALRM);
|
|
|
+ }
|
|
|
+ count--;
|
|
|
+}
|
|
|
+
|
|
|
+int main(int argc, char** argv) {
|
|
|
+ int ret;
|
|
|
+ sig_stack = malloc(sig_stack_size);
|
|
|
+ if (sig_stack == NULL) {
|
|
|
+ err(EXIT_FAILURE, "malloc");
|
|
|
+ }
|
|
|
+
|
|
|
+ stack_t ss = {
|
|
|
+ .ss_sp = sig_stack,
|
|
|
+ .ss_flags = 0,
|
|
|
+ .ss_size = sig_stack_size,
|
|
|
+ };
|
|
|
+ stack_t old;
|
|
|
+ memset(&old, 0xff, sizeof(old));
|
|
|
+ ret = sigaltstack(&ss, &old);
|
|
|
+ if (ret < 0) {
|
|
|
+ err(EXIT_FAILURE, "sigaltstack");
|
|
|
+ }
|
|
|
+ if (old.ss_flags & SS_ONSTACK) {
|
|
|
+ printf("FAIL on sigaltstack in main thread before alarm\n");
|
|
|
+ } else {
|
|
|
+ printf("OK on sigaltstack in main thread before alarm\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ struct sigaction act;
|
|
|
+ act.sa_sigaction = handler;
|
|
|
+ sigemptyset(&act.sa_mask);
|
|
|
+ act.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
|
|
|
+ ret = sigaction(SIGALRM, &act, NULL);
|
|
|
+ if (ret < 0) {
|
|
|
+ err(EXIT_FAILURE, "sigaction");
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("&act == %p\n", &act);
|
|
|
+ fflush(stdout);
|
|
|
+ alarm(1);
|
|
|
+ pause();
|
|
|
+
|
|
|
+ memset(&old, 0xff, sizeof(old));
|
|
|
+ ret = sigaltstack(NULL, &old);
|
|
|
+ if (ret < 0) {
|
|
|
+ err(EXIT_FAILURE, "sigaltstack");
|
|
|
+ }
|
|
|
+ if (old.ss_flags & SS_ONSTACK) {
|
|
|
+ printf("FAIL on sigaltstack in main thread\n");
|
|
|
+ } else {
|
|
|
+ printf("OK on sigaltstack in main thread\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("done exiting\n");
|
|
|
+ fflush(stdout);
|
|
|
+ return 0;
|
|
|
+}
|