繁体   English   中英

工作者线程堆栈溢出时的信息出口

[英]Informative exit on stack overflow in worker thread

我正在编写一个C ++程序,该程序将在递归数据上运行一堆工作线程,这样,即使我增加了默认的堆栈空间,线程也有可能遇到堆栈溢出。

理想的做法是使堆栈根据需要动态扩展,但是如果不可能,则可以使程序失败,并让用户在使用较大的堆栈大小重新编译后重试。

程序默认行为崩溃而没有任何错误消息的问题是用户无法知道问题出在哪里或如何解决。 就用户所知,该程序可能试图除以零或取消引用空指针; 因此,如果程序必须崩溃,我希望它首先将“ Stack Overflow”打印到stderr。

显然,在便携式C ++中不会有一种解决方案,但是我对一种适用于Windows的解决方案和另一种适用于Linux的解决方案感到满意。

在寻找使程序在Windows上退出并显示提示性错误消息的方法时,我一直在阅读有关矢量化和结构化异常处理的文档。 一个问题是它们似乎是线程本地的,并且线程不能安全地写入stderr。 最好情况下,您会遇到种族问题。

有已知的处理方法吗?

该操作系统(至少具有Linux或Unix风格)使您能够捕获堆栈故障。

像这样:

 // Note: Calling printf here is probably not a brilliant idea, 
 // as we're in a signal handler. It is NOT well-defined what happens.
 void handler(int arg)
 {
    fprintf(stderr, "Crashed due to signal handler\n"); 
    exit(42);
 }

然后主要是这样的...

 struct sigaction sa = { handler, NULL, 0, 0, NULL };
 struct sigaction oldsa;
 sigaction(SIGSTKFLT, sa, oldsa);

我将尝试提出一些“完整”的解决方案,并进行一些实验。

(我相信可以替换堆栈,但我认为您不能以有意义的方式实际上继续执行该操作,而只是让您以比崩溃更明智的方式恢复!)

这似乎可以正常工作:

#include <signal.h>
#include <unistd.h>
#include <iostream>
#include <cstdlib>

void handler(int arg)
{
    write(2, "stack overflow\n", 15);
    _exit(42);
}

void* duh(void *arg)
{
    if(duh(arg))
    {
        return duh(NULL);
    }
    else
    {
        return duh(arg);
    }
}

void* crash_wrapper(void *arg)
{
    static char stack[SIGSTKSZ];
    stack_t ss = {};
    ss.ss_sp = stack;
    ss.ss_size = SIGSTKSZ;
    sigaltstack(&ss, 0);

    struct sigaction sa = {};
    sa.sa_handler = handler;
    sa.sa_flags = SA_ONSTACK,
    sigfillset(&sa.sa_mask);
    sigaction(SIGSEGV, &sa, 0);

    return duh(arg);
}

int main()
{
    pthread_t t;
    int status = pthread_create(&t, 0, crash_wrapper, 0 );

    for(;;)
    {
        std::cout << "Still going..." << std::endl;
        sleep(1);
    }
}

我对处理程序中的write不完全满意,但是我尝试过的所有其他方法似乎也不起作用... :(

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM