使用 native_handle() + pthread_cancel() 取消 std::thread
Posted
技术标签:
【中文标题】使用 native_handle() + pthread_cancel() 取消 std::thread【英文标题】:cancelling std::thread using native_handle() + pthread_cancel() 【发布时间】:2012-11-23 14:40:03 【问题描述】:我正在将先前围绕 pthreads 的线程包装器转换为 std::thread。 但是 c++11 没有任何方法可以取消线程。尽管如此,我还是需要取消线程,因为它们可能在外部库中执行非常冗长的任务。
我正在考虑在我的平台上使用为我提供 pthread_id 的 native_handle。我在 Linux(Ubuntu 12.10)中使用 gcc 4.7。这个想法是:
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
int main(int argc, char **argv)
cout << "Hello, world!" << endl;
auto lambda = []()
cout << "ID: "<<pthread_self() <<endl;
while (true)
cout << "Hello" << endl;
this_thread::sleep_for(chrono::seconds(2));
;
pthread_t id;
std::thread th(lambda);
this_thread::sleep_for(chrono::seconds(1));
id = th.native_handle();
cout << id << endl;
th.detach();
cout << "cancelling ID: "<< id << endl;
pthread_cancel(id);
cout << "cancelled: "<< id << endl;
return 0;
线程被 pthreads 抛出的异常取消。
我的问题是:
这种方法会不会有什么问题(除了不便携)?
【问题讨论】:
pthreads 不能抛出异常。它是一个 C 库,C 中没有例外。 我不知道如何抛出异常的确切技术细节,但一个是......只需尝试在 lambda 中添加“trycodecatch(...)”和一个在 main() 结束时休眠,你会得到“FATAL: exception not rethrown”。 请注意,取消线程有各种副作用,包括内存泄漏。如果您负担得起,请不要取消线程。曾经。最好在每个线程中使用atomic<bool>
变量,而不是在 while 条件下读取。
如果您的目的是退出应用程序,您不必担心内存泄漏。它在应用程序退出时被清理。您只需要担心泄漏任何超出您的应用程序的资源(例如,进程间信号量)。您的应用程序可能不拥有任何此类资源。如果是这样的话,我会说你的原始代码很好。
@JoãoLeal:异常很可能是由std::thread
对象引发的。 Pthread 取消通常通过向线程发出信号来工作。 std::thread
可能会以某种方式与之交互。
【参考方案1】:
不,我认为您不会遇到以下问题:
不便携 必须小心地编程_very_very_,以使被取消线程的所有对象都被销毁...例如,标准规定当线程结束时,变量将被销毁。如果你取消一个线程,这对编译器来说会更加困难,如果不是不可能的话。
因此,如果您能以某种方式避免它,我会建议 不 取消一个线程。编写一个标准的轮询循环,使用条件变量,监听信号以中断读取等等——并定期结束线程。
【讨论】:
取消线程只会导致线程退出,就好像抛出了异常并且从未被捕获......所以我想正常的内存处理仍然可以工作。不幸的是,提供的代码不正确......如果在 main 的末尾添加了 sleep 将会出现分段错误。我还不知道原因... :( @joao-leal:真的,“好像抛出了异常”?我可以想象它,但听起来很难实现。我发现“未定义的行为”更直接。你能指出标准中提到的地方吗?我是否正确地记得线程中未捕获的异常会被忽略 - 例如,它不会在整个程序上调用terminate()
?
与 c++ 标准无关,但 pthreads 的工作方式:cursuri.cs.pub.ro/~apc/2003/resources/pthreads/uguide/…
@joao-leal:我明白了。谢谢你。但是 C++11 的工作方式可能与 pthread 完全不同。如果您使用 pthreads,则 pthreads 规范是相关的。如果您使用 C++11,则该规范是相关的。以上是关于使用 native_handle() + pthread_cancel() 取消 std::thread的主要内容,如果未能解决你的问题,请参考以下文章
Windows下JetBrains CLion的pthread使用配置