我试图在c ++中了解pthread_cancel在linux环境中的用法。但我遇到了运行时问题。
class A {
public:
A(){cout<<"constructor\n";}
~A(){cout<<"destructor\n";}
};
void* run(void* data) {
A a;
while(1) {
//sleep(1);
cout<<"while\n";
}
}
int main() {
pthread_t pid;
pthread_create(&pid,NULL,run,NULL);
sleep(2);;
pthread_cancel(pid);
cout<<"Canceled\n";
pthread_exit(0);
}
constructor
while
"
"
while
Canceled
FATAL: exception not rethrown
Aborted (core dumped)
(gdb) where
#0 0x00000036e8c30265 in raise () from /lib64/libc.so.6
#1 0x00000036e8c31d10 in abort () from /lib64/libc.so.6
#2 0x00000036e9c0d221 in unwind_cleanup () from /lib64/libpthread.so.0
#3 0x00000036fa69042b in std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) () from /usr/lib64/libstdc++.so.6
#4 0x00000000004009c5 in run(void*) ()
#5 0x00000036e9c0677d in start_thread () from /lib64/libpthread.so.0
#6 0x00000036e8cd49ad in clone () from /lib64/libc.so.6
但是,如果我在线程函数运行中取消注释sleep(1),我的输出低于输出。 构造函数 而 取消 析
你能否解释一下为什么该计划正在给予&#34;致命:例外而不是重新投入&#34;在第一种情况下而不在第二种情况下请详细解释为什么pthread_cancel比pthread_kill更安全?
答案 0 :(得分:1)
很抱歉成为坏消息的承担者,但要让pthread_cancel在Linux的C ++中正常工作很困难。
原因是Linux中的pthread_cancel方法实现绝对可怕。特别是它会引发异常(在我撰写本文时为abi::__forced_unwind
)。这在C程序中可能很好,但是在C ++中,很难正确处理线程取消。特别是,如果您有任何吞噬异常的代码(例如catch (...)
),则此内部异常将被处理并且不会按照需要的方式传递到堆栈中。在这种情况下,您将看到所看到的错误消息。
也就是说,我看不出您的代码中有什么会“吃掉”该异常,但是我怀疑是这种性质的问题导致了此问题。
在您的特定示例中,当您要退出而不调用pthread_cancel时,可以通过使用标志或类似便笺的方式轻松解决此问题。不幸的是,这使sleep
变得更加复杂(您需要以很小的间隔多次调用它以检查标志),并且几乎不可能调用accept
(必须从另一个端口连接到该端口)强制accept
退出的线程或进程,以便您可以检查变量)。关于线程取消的一般问题(https://lwn.net/Articles/683118/)进行了很长的讨论,但是鉴于macOS(以及大概其他非Linux的“ unixes”)似乎处理得很好,我真的认为Linux实现可以做得更好。但是在完成该操作之前,pthread_cancel将仍然非常难以使用。
答案 1 :(得分:0)
我的猜测是,这与取消点有关。默认情况下,新线程具有取消类型PTHREAD_CANCEL_DEFERRED
。这意味着pthread_cancel
在线程点击其中一个预定义的取消点之前不会做任何事情。 sleep
是已定义的取消点之一,但std::cout::operator<<
不是(pthreads'手册页列出了所有取消点)。因此,当你的sleep
注释掉时,线程永远不会到达取消点,而pthreads会抛出一个拟合。您可以使用pthread_setcanceltype
将线程设置为PTHREAD_CANCEL_ASYNCHRONOUS
,但这至少会导致我的系统出现问题。
您最好的选择可能是使用std::thread
而不是直接处理pthreads。该库实际上是为了与C ++正常工作而设计的。