Как использовать "sigaltstack" в программе обработки сигналов?

Кто-нибудь, кто знает, как использовать sigaltstack в реальной программе обработки сигналов, простой, но полный код может быть очень полезной для меня! заранее спасибо!

Ответ 1

Вот минимальная программа-образец, которая использует sigaltstack для поиска бесконечной рекурсии. Если вы закомментируете флаг sigaltstack или SA_ONSTACK, обработчик сигнала не сможет работать, потому что у него нет стека слева, и программа просто сработает.

#define _XOPEN_SOURCE 700
#include <signal.h>
#include <unistd.h>
void handler(int sig)
{
    write(2, "stack overflow\n", 15);
    _exit(1);
}
unsigned infinite_recursion(unsigned x) {
    return infinite_recursion(x)+1;
}
int main()
{
    static char stack[SIGSTKSZ];
    stack_t ss = {
        .ss_size = SIGSTKSZ,
        .ss_sp = stack,
    };
    struct sigaction sa = {
        .sa_handler = handler,
        .sa_flags = SA_ONSTACK
    };
    sigaltstack(&ss, 0);
    sigfillset(&sa.sa_mask);
    sigaction(SIGSEGV, &sa, 0);
    infinite_recursion(0);
}

Более сложное использование может фактически выполнить siglongjmp, чтобы выскочить из обработчика сигнала и вернуться в точку, где можно избежать бесконечной рекурсии. Это недопустимо, если используются вызовы с использованием небезопасной библиотеки, а также если ваши данные могут быть оставлены в небезопасном/невосстановимом состоянии, но если вы выполняете чистые арифметические вычисления, это может быть действительно.

Возможно, лучшей задачей для обработчика сигнала будет выполнение аварийного дампа любых ценных/критических данных, которые еще не были сохранены на диске. Это может быть затруднено, если вы не можете вызывать небезопасные функции async-signal, но это обычно возможно, если вы приложите к нему какое-то усилие.