Tej*_*ula 4 c++ linux multithreading
我试图了解 pthread_cancel 在 c++ 中的 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);
}
Run Code Online (Sandbox Code Playgroud)
constructor
while
while
...
while
while
Canceled
FATAL: exception not rethrown
Aborted (core dumped)
Run Code Online (Sandbox Code Playgroud)
(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
Run Code Online (Sandbox Code Playgroud)
但是,如果我取消注释线程函数运行中的 sleep(1),我将得到以下输出。
constructor
while
Canceled
destructor
Run Code Online (Sandbox Code Playgroud)
您能否解释一下为什么程序在第一种情况下给出“致命:异常未重新抛出”而不是在第二种情况下给出?请举例详细解释为什么pthread_cancel比pthread_kill更安全?
抱歉要告诉大家一个坏消息,但是在 Linux 的 C++ 中让 pthread_cancel 正常工作是非常困难的。
原因是 Linux 中的 pthread_cancel 方法实现绝对是可怕的。特别是它会导致抛出异常(abi::__forced_unwind截至我撰写本文时)。这在 C 程序中可能没问题,但在 C++ 中,它使得正确处理线程取消变得非常困难。特别是,如果您有任何处理异常的代码(例如catch (...)),则此内部异常将被处理,并且不会按需要的方式向上传递到堆栈。在这种情况下,您将看到您所看到的错误消息。
也就是说,我不知道你的代码中的什么会“吃掉”这个异常,但我怀疑正是这种性质导致了问题。
在您的特定示例中,当您想要退出而不调用 pthread_cancel 时,可以通过使用标志或类似的注释来轻松解决此问题。不幸的是,这使得sleep更加复杂(您需要以较小的间隔多次调用它才能检查标志)并且调用accept几乎不可能(您必须从另一个线程或进程连接到端口以强制accept退出,这样您就可以检查变量)。一般来说,关于线程取消的问题有一个很长的讨论(https://lwn.net/Articles/683118/),但考虑到 macOS(可能还有其他非 Linux“unix”)似乎处理得很好,我真的认为Linux的实现可以做得更好。但在此之前,pthread_cancel 仍然很难使用。
| 归档时间: |
|
| 查看次数: |
7710 次 |
| 最近记录: |