线程取消(pthread)& C ++

时间:2010-11-19 12:19:26

标签: c++ linux multithreading pthreads cancellation

我正在用C ++编写Linux程序,我想知道如何执行线程取消。

据我所知,当线程被取消时,在线程函数内部调用清理函数,强制线程函数退出。这意味着两件事:

  1. 当线程被取消时,它仍会调用在线程函数内创建的所有C ++对象的析构函数。
  2. 我可以传递给在线程函数中创建的对象的清理函数指针。
  3. 我是对的并且下面的代码工作得很好吗?


    下面的代码中还有一个问题,当线程在 SECTION A 中被取消时, second_thread_cleanup_function()将首先被调用,对吗?

    class SomeObject
    {
        public:
            ~SimpleObject (void); // <- free dynamically allocated memory
    
            void finalize (void);
    
            // ...
    }
    
    void first_thread_cleanup_function (void* argument)
    {
        SomeObject* object (argument);
    
        object->finalize ();
    }
    
    void second_thread_cleanup_function (void* argument)
    {
        // ... do something ...
    }
    
    void* thread_function (viod* argument)
    {
        SomeObject object;
    
        pthread_cleanup_push (first_thread_cleanup_function, &object);
    
        // ... some code ...
    
        pthread_cleanup_push (second_thread_cleanup_function, NULL);
        // ... SECTION A ...
        pthread_cleanup_pop (0);
    
        // .. some code ...
    
        pthread_cleanup_pop (1);
    }
    

3 个答案:

答案 0 :(得分:2)

只有在清理方法中释放已分配的对象时,才会调用析构函数。否则,没有。

是的,你在A节中有清理电话的顺序。

答案 1 :(得分:1)

使用NPTL的任何现代Linux发行版(实际上意味着任何运行2.6内核),NPTL将调用析构函数并使用伪异常展开堆栈。

事实上,NPTL通过实现所谓的强制堆栈展开来坚持它。您可以使用catch(...)捕获伪异常,但如果您这样做,则必须随后重新抛出它,否则整个过程将被终止。

克里斯

答案 2 :(得分:1)

取消的线程堆栈没有被解除的断言 - 导致本地对象的非破坏 - 与@Chris断言线程的堆栈被解开并且使用以下反例例:

#include <climits>
#include <iostream>
#include <pthread.h>
#include <thread>
#include <unistd.h>

class Obj {
public:
    Obj()  { std::clog << "Obj() called\n"; }
    ~Obj() { std::clog << "~Obj() called\n"; }
};

static void cleanup(void* arg) {
    std::clog << "cleanup() called\n";
}

static void run() {
    Obj obj{}; // Local object
    pthread_cleanup_push(cleanup, nullptr);
    ::pause(); // Thread cancelled here
    pthread_cleanup_pop(1);
}

int main(int argc, char **argv) {
    std::thread thread([]{run();});
    ::sleep(1);
    ::pthread_cancel(thread.native_handle());
    thread.join();
}

执行时,上面的程序表明当线程被取消时,确实调用了本地对象的析构函数:

$ ./a.out 
Obj() called
cleanup() called
~Obj() called
$