使用 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&lt;bool&gt; 变量,而不是在 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使用配置

达到计数32751后无法创建线程

boost::interprocess 准备好迎接黄金时段了吗? [关闭]

基于pthread的线程池实现

获取线程ID