#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

#define SIGNAL SIGUSR1
#define PRINT(msg) write(1, msg, strlen(msg))

struct sigaction previous_sighandler;

static void faulthandler_user(int signum);

static void
faulthandler_register(int signum, struct sigaction *old_sighandler)
{
    struct sigaction action;
    action.sa_handler = faulthandler_user;
    sigemptyset(&action.sa_mask);
    action.sa_flags = SA_RESTART;
    action.sa_flags = SA_NODEFER;
    action.sa_flags |= SA_ONSTACK;
    sigaction(signum, &action, old_sighandler);
}

static void
faulthandler_user(int signum)
{
    const char* msg = "our signal handler\n";
    PRINT(msg);

    (void)sigaction(signum, &previous_sighandler, NULL);
    raise(signum);
    (void)faulthandler_register(signum, NULL);
}


int main(void)
{
    const char *msg = "exit\n";
    static stack_t stack;
    int res;

    stack.ss_flags = 0;
    stack.ss_size = SIGSTKSZ;
    stack.ss_sp = malloc(stack.ss_size);
    if (stack.ss_sp == NULL) {
        PRINT("out of memory\n");
        return 1;
    }
    printf("SIGSTKSZ = %zu\n", (size_t)SIGSTKSZ);

    res = sigaltstack(&stack, NULL);
    if (res) {
        free(stack.ss_sp);
        PRINT("sigaltstack failed\n");
        return 1;
    }

    faulthandler_register(SIGNAL, &previous_sighandler);
    raise(SIGNAL);


    PRINT(msg);
    free(stack.ss_sp);

    return 0;
}
