Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 保护主线程不受工作线程错误的影响_C++_C_Pthreads_Signals_Posix - Fatal编程技术网

C++ 保护主线程不受工作线程错误的影响

C++ 保护主线程不受工作线程错误的影响,c++,c,pthreads,signals,posix,C++,C,Pthreads,Signals,Posix,在使用posix线程时,是否有某种方法可以“保护”主线程不受工作线程引起的错误(如取消引用的空指针、零除法等)的影响。我所说的“工作线程”是指由pthread_create()创建的posix线程 不幸的是,我们不能使用异常——因此没有“catch”等 这是我的测试程序(C++): void*workerThreadFunc(void*threadId){ int*a=NULL; *a=5;//错误(分段错误) pthread_exit(NULL); } int main(){ cout假设您的

在使用posix线程时,是否有某种方法可以“保护”主线程不受工作线程引起的错误(如取消引用的空指针、零除法等)的影响。我所说的“工作线程”是指由pthread_create()创建的posix线程

不幸的是,我们不能使用异常——因此没有“catch”等

这是我的测试程序(C++):

void*workerThreadFunc(void*threadId){
int*a=NULL;
*a=5;//错误(分段错误)
pthread_exit(NULL);
}
int main(){

cout假设您的系统以某种方式使用POSIX信号(尽管这可能属于“无例外”规则),那么POSIX会说:

在生成时,应确定是为进程还是为进程内的特定线程生成了信号。应为导致生成信号的线程生成由特定线程的某些操作(如硬件故障)生成的信号

因此,您可以在每个pthread的基础上处理
SIGSEGV
SIGFPE
等(但请注意,您只能为整个进程设置一个信号处理函数)。因此,您可以“保护”在某种程度上,进程不会因为单个pthread中的故障而停止。当然,问题是,您可能会发现很难判断进程(失败的pthread和所有其他pthread)处于何种状态。失败的pthread可能持有大量互斥体。失败的pthread可能会留下一些共享数据乱七八糟的结构。谁知道什么样的东西是乱七八糟的——除非pthread本质上是独立的。可以安排其他pthread“优雅地”关闭…而不是崩溃和烧坏。最终,停止所有pthread可能会更安全,而不是试图在某些定义不明确的状态下继续。这将完全取决于应用程序的性质


什么都不是白做的…线程之间的通信比进程更容易,启动和停止的成本更低——进程不太容易受到其他进程失败的影响。

我能想到的唯一方法是注册一个信号处理程序,它可以取消当前正在运行的程序,而不是中止程序广告,类似这样:

void handler(int sig)
{
    pthread_exit(NULL);
}

signal(SIGSEGV, handler);

但是,请注意,这是不安全的,因为
pthread\u exit
未列为信号处理程序中的安全系统调用之一。它可能工作,也可能不工作,这取决于您运行的操作系统以及您处理的信号。

听起来您应该使用多个进程,而不是线程。独立进程是aut在其他进程中不会发生此类错误

您可以使用管道或共享内存(或其他形式的IPC)在线程之间传递数据,这还有一个额外的好处,即只共享您想要共享的内存,因此工作线程中的错误不能踩在主线程的堆栈上,因为它是一个具有单独地址空间的单独进程


线程可能很有用,但也有一些缺点,有时在单独的进程中运行更合适。

'不幸的是,我们不能使用异常-因此没有“捕获”,等等。-当然可以。异常将在引发它的线程中抛出。保护其他线程不受异常/错误影响的最佳方法是修复它们,以便它们不会发生或被检测到并处理/记录/whatever.Note-在上面的示例中,您正试图加入一个尚未创建的线程。@MartinJames啊,是的,您是正确的t、 谢谢。虽然将行复制到我的示例中只是一个简单的错误(我的实际程序以正确的顺序运行)。我将编辑我的帖子。@MartinJames“当然可以。异常将在引发它的线程中引发”。我们的代码需要为一个没有异常支持的系统进行编译。谢谢。至少现在在一个简单的测试中,这似乎可以做到这一点。我需要研究您提到的安全问题。如果在该线程堆栈上创建了一个对象,并且该对象定义了析构函数,那么pthread_exit似乎会导致SIGABRT。这将要么导致捕获的SIGABRT的无限循环(如果在sighandler中捕获它们),要么导致完整的程序崩溃。例如,如果我声明一个非常简单的结构的对象,就会发生这种情况。如果该对象定义了析构函数,甚至只定义了~a(){},它就会崩溃。但如果未定义此析构函数,则不会发送SIGABRT。如果我声明一个向量,也会出现此问题。所谓“进程”是指例如fork()?是,
fork()
master的新子进程,以及
exec()
为工作程序创建一个不同的可执行文件,或者继续运行同一个可执行文件,但让子文件在“工作程序”模式下运行。
void handler(int sig)
{
    pthread_exit(NULL);
}

signal(SIGSEGV, handler);