2009-11-02 10 views
9

Veo un problema por el que una llamada a boost's thread-> join en un destructor lleva a un interbloqueo. No entiendo por qué, y no estoy muy interesado en mantener el código que simplemente funciona (y no entiendo por qué lo hace) en el proyecto.Unir una instancia boost :: thread en el destructor

Declaración de clase (he despojado el método run() de try/catch para abreviar: de acuerdo a la documentación hilo impulso, el resultado debe ser el mismo con o sin ella):

class B 
{ 
public: 
    void operator()(){run();} 
    void run(); 
    void shutdown(); 
    ~B(); 
    B(); 
    boost::thread *thr; 
    bool shutdown_requested; 
}; 

void B::shutdown() 
{ 
    shutdown_requested = true; 

    if (thr != NULL) 
    { 
     thr->interrupt(); 
     thr->join(); // deadlock occurs here! 
     delete thr; 
     thr = NULL; 
    } 
} 

B::~B() 
{ 
    shutdown(); 
} 

B::B() 
{ 
    thr = new boost::thread(boost::ref(*this)); 
} 

void B::run() 
{ 
    while (!shutdown_requested) 
    { 
     boost::xtime xt; 
     boost::xtime_get(&xt, boost::TIME_UTC); 
     xt.sec += 30; 
     boost::this_thread::sleep(xt); 
    } 
} 

de fragmentos que no funciona:

int main() 
{ 
    B *b = new B; 

    Sleep(5000); 
    printf("deleting \n");fflush(stdout); 
// b->shutdown(); 
    delete b; 
    printf("done\n");fflush(stdout); 

    return 0; 
} 

de fragmentos que trabaja:

int main() 
{ 
    B *b = new B; 

    Sleep(5000); 
    printf("deleting \n");fflush(stdout); 
    b->shutdown(); 
    delete b; 
    printf("done\n");fflush(stdout); 

    return 0; 
} 

creo que el razón de este comportamiento tiene algo que ver con este fragmento de la documentación impulso:

el usuario debe asegurarse de Boost.Thread que el referido-a-objeto sobrevive el hilo de nueva creación de la ejecución.

Pero realmente no entiendo por qué el punto muerto: unir el hilo no llamaría al destructor en B y el objeto no se eliminará cuando se supone que el método run() debe salir.

+1

Buena pregunta, y bien hecho. No sé una respuesta, pero ¿has echado un vistazo a la implementación de boost :: thread? ¿O has intentado depurarlo? Tal vez eso te da una pista. Al mirar el código de ejemplo, diría que debería funcionar bien. – MP24

+0

Gracias, encontré el problema al entrar en el depurador. Estaba relacionado con el código de detección de fugas. – laura

Respuesta

4

He encontrado el problema: todo se reduce a un programador excesivamente celoso.

Originalmente había compilado mi proyecto usando DUMA (http://sourceforge.net/projects/duma/) para ver si mi implementación del módulo actual no tenía fugas. Desafortunadamente, mi sandbox de prueba también tenía las configuraciones de duma, que no me di cuenta hasta que revisé el código en un depurador.

Después de eliminar toda la detección de fuga de memoria, todo funciona como se esperaba.

+0

Tenga en cuenta que puede aceptar su propia respuesta para marcar su pregunta como respondida. – MP24

+0

Desafortunadamente después de dos días. Gracias de nuevo por la ayuda – laura

Cuestiones relacionadas