Hilo de cancelación (pthread) & C ++
-
26-09-2019 - |
Pregunta
programa de MT estoy escribiendo para Linux en C ++ y quiero saber cómo se realiza la cancelación hilo.
Por lo que yo entiendo cuando el hilo se cancela funciones de limpieza se llaman dentro de la función del hilo y la función del hilo se ve obligado a salir. Este significar dos cosas:
- Cuando el hilo se cancela todavía llama a los destructores fo todos los objetos de C ++ creado dentro de la función del hilo.
- Me puede pasar a funciones de limpieza punteros a objetos creados en función del hilo.
Estoy en lo cierto y el código de abajo el trabajo enfermo de bien?
Una pregunta más en el código siguiente, cuando el hilo se cancela en algún lugar de A , second_thread_cleanup_function () será llamado en primer lugar, ¿verdad?
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);
}
Solución
Con cualquier distribución de Linux moderno usando NPTL (que en la práctica significa cualquier ejecución de un kernel 2.6), NPTL llamará destructores y descansar la pila con un pseudo-excepción.
De hecho NTPL insiste en que, mediante la implementación de lo que llama pila obligado desenrollar. Se puede coger el seudo-excepción con el retén (...), pero si lo hace por lo que posteriormente debe volver a lanzar o será terminado todo el proceso.
Chris
Otros consejos
Los destructores sólo se llama suponiendo que liberará los objetos asignados en los métodos de limpieza. De lo contrario, no.
Y sí, usted tiene el orden de las llamadas de limpieza en la sección A correcta.
La afirmación de que la pila de un hilo cancelada no es desenrollada - que resulta en la no destrucción de objetos locales - es incompatible con la afirmación de que @ Chris pila del hilo se desenrolla y con el contra-ejemplo siguiente:
#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();
}
Cuando se ejecuta, el programa anterior indica que destructor del objeto local es, de hecho, llama cuando se cancela el hilo:
$ ./a.out
Obj() called
cleanup() called
~Obj() called
$