Linux上的PTHREAD_CANCEL()导致异常/Coredump,为什么
pthread_cancel() on linux leads to exception/coredump, why?
我正在测试pthread_cancel的行为。
#include<pthread.h>
#include<unistd.h>
#include<iostream>
using namespace std;
int retval=70;
void* tf(void*arg){
int oldstate;
int i=0;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
while(true){
cout<<"sleep 1"<<endl;
sleep(1);
++i;
if(i==5){//response to last pthread_cancel()?
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
}
}
return NULL;
}
int main(){
pthread_t tid;
pthread_create(&tid,NULL,tf,NULL);
sleep(2);
pthread_cancel(tid);//not responded until "PTHREAD_CANCEL_ENABLE"?
cout<<"cancel thread"<<endl;
pthread_join(tid,NULL);
return 0;
}
我期望
(1(何时禁用取消呼叫,任何对PTHREAD_CANCEL的呼叫将被忽略,但应记住呼叫
(2(直到启用取消为止:它将检查是否有以前的呼叫pthread_cancel,如果是,则可以取消。
sleep 1
sleep 1
cancel thread
sleep 1
sleep 1
sleep 1
sleep 1
但是在我的Linux服务器上,它打印:
sleep 1
sleep 1
cancel thread
sleep 1
sleep 1
sleep 1
FATAL: exception not rethrown
sleep 1
Aborted (core dumped)
不知道发生了什么事,以及致命的例外情况如何?我应该有一些错误的理解。需要您的建议!
线程取消点,C 彼此之间的状态不佳。想想线程堆栈中局部变量会发生什么,当线程被取消时,它们的破坏者是否被称为
。从历史上看,关于此的辩论已经存在一些辩论,许多Pthread实现的选择不同。有些人甚至会以与C 异常相同的机制实施取消,以便堆栈可以很好地解开。但是,一个放置良好的catch
会弄乱问题...
但是,pthread_cancel
是一种POSIX结构,因此仅适用于c。
也就是说,编译器会尽力而为。就您而言,这可能是编译器或某些库中的错误(您不说什么编译器版本以及您使用的编译器命令...(。您的代码对我有效(GCC 7.1和Clang 4.0.1(。
但是,如果我添加这样的 try/catch
,它就像你的失败:
void* tf(void*arg) {
try {
//your code
} catch (...) {
return NULL;
}
}
但是,如果我在 catch
末尾重新恢复异常,它将再次工作正常:
void* tf(void*arg) {
try {
//your code
} catch (...) {
throw;
}
}
证明我的C 编译器pthread_cancel
使用与C 异常相同的机制。我的猜测是,当线程以C 模式取消时,它会引发内部异常,并希望在线程函数的母体上捕获它。但是,如果您正常从线程函数返回,则该线程已取消,则显示此消息。
,由于您没有这样做,因此有几种解释:
- 您正在使用不支持C 和Pthread取消的编译器。
- 您版本的编译器/库中的错误。
- 您正在混合编译器/库的不同版本。也许您正在混合C和C 库。
ps 1:我检查了在线程函数中添加带有非琐碎破坏者的局部变量,我确认当线程完成时调用了破坏者。
。 ps 2:我从线程函数中检查了pthread_exit()
,无需取消,并且还调用了本地破坏者。如果我围绕pthread_exit()
进行try/catch(...)
,则使用相同的FATAL: exception not rethrown
失败。因此,pthread_exit()
和pthread_cancel()
使用相同的基础机制。
ps 3:所有看起来都非常好,但是线程取消仍然可以在任何时候发生:如果线程取消发生在cout.operator<<()
的中间例如,本地破坏者(根本不起作用。
它在运行Linux的PC上工作正常。
$ g++ try.cc -o try -lpthread
$ ./try
sleep 1
sleep 1
cancel thread
sleep 1
sleep 1
sleep 1
sleep 1
$
- 处理多个异常集合的C++方法
- 我在c++代码中生成了一个运行时#3异常
- 孤立代码块在结构中引发异常
- C++中的赋值发生,尽管右侧出现异常
- 从构造函数抛出异常时如何克服内存泄漏
- 异常属于C++中的线程还是进程
- 当类定义不可见时捕获异常
- 引发异常:读取访问冲突**dynamicArray**为0x1118235.发生
- 为什么异常不退出程序?
- 为什么我应该在异常处理中使用std::cerr而不是std::cout
- 如何修复链表类实现的未处理异常0xDDDDDDDD
- 关于:C++中异常对象的范围:为什么我没有得到副本?
- 是什么导致了Unity 3D中的"错误线程异常"?
- 如何将strftime中的格式错误作为异常捕获
- 创建具有 new in 函数和"this is nullptr"异常的对象
- 尝试使用智能指针时引发异常
- 函数如何通知用户它基于函数原型抛出异常?
- 是否值得降低我的代码的可读性,以便在出现内存不足错误时提供异常安全性?
- 当我使用 C++ 中的 C# dll 来使用 Selenium 时,存在异常处理问题
- Linux上的PTHREAD_CANCEL()导致异常/Coredump,为什么