Отмена потока (pthread) и C ++ - PullRequest
       23

Отмена потока (pthread) и C ++

1 голос
/ 19 ноября 2010

Я пишу программу MT для Linux на C ++, и я хочу знать, как выполняется отмена потока.

Насколько я понимаю, когда поток отменяется, функции очистки вызываются внутри функции потока и функции потокавынужден выйти.Это означает две вещи:

  1. Когда поток отменяется, он по-прежнему вызывает деструкторы для всех объектов C ++, созданных внутри функции потока.
  2. Я могу перейти к указателям на функции очистки для объектов, созданных в функции потока.

Правильно ли я и код ниже плохо работает?


Еще один вопрос в коде ниже, когда поток отменяется где-то в РАЗДЕЛ 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 ]

2 голосов
/ 19 ноября 2010

Деструкторы будут вызываться только при условии, что вы освободите выделенные объекты в методах очистки. В противном случае, нет.

И да, у вас есть порядок очистки вызовов в разделе A правильно.

1 голос
/ 02 мая 2017

Утверждение о том, что стек отмененного потока не разматывается, что приводит к неразрушению локальных объектов, несовместимо с утверждением @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
$ 
1 голос
/ 31 января 2011

В любом современном дистрибутиве Linux, использующем NPTL (что на практике означает любое работающее с ядром 2.6), NPTL будет вызывать деструкторы и разматывать стек с псевдо-исключением.

Фактически NPTL настаивает на этом,реализуя то, что называется принудительным разматыванием стека.Вы можете перехватить псевдо-исключение с помощью catch (...), но если вы это сделаете, вы должны впоследствии сбросить его, или весь процесс будет прерван.

Chris

...