pthread Independiente sencilla no cancela! (Bloques cout e intercala incluso si mutexed)

StackOverflow https://stackoverflow.com/questions/2440576

  •  19-09-2019
  •  | 
  •  

Pregunta

Tengo un problema difícil aquí, que no puedo resolver y no encontrar la respuesta correcta en la red:

He creado un hilo independiente con una limpieza de enrutamiento, el problema es que en mi Imac y Ubuntu 9.1 (Dual Core). No soy capaz de cancelar correctamente el hilo individual en el código barbecho:

#include <iostream>
#include <pthread.h>
#include <sched.h>
#include <signal.h>

#include <time.h>

pthread_mutex_t mutex_t;

using namespace std;

static void cleanup(void *arg){
    pthread_mutex_lock(&mutex_t);
    cout << " doing clean up"<<endl;
    pthread_mutex_unlock(&mutex_t);
}


static void *thread(void *aArgument)
{

    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);

    pthread_cleanup_push(&cleanup,NULL);
    int n=0;
    while(1){
        pthread_testcancel();
        sched_yield();
        n++;

        pthread_mutex_lock(&mutex_t);
        cout << " Thread 2: "<< n<<endl; // IF I remove this endl;  --> IT WORKS!!??
        pthread_mutex_unlock(&mutex_t);

    }
    pthread_cleanup_pop(0);

    return NULL;
}


int main()
{

    pthread_t thread_id;

    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

    int error;

    if (pthread_mutex_init(&mutex_t,NULL) != 0) return 1;

    if (pthread_create(&thread_id, &attr, &(thread) , NULL) != 0) return 1;

    pthread_mutex_lock(&mutex_t);
    cout << "waiting 1s for thread...\n" <<endl;
    pthread_mutex_unlock(&mutex_t);

    int n =0;

    while(n<1E3){
        pthread_testcancel();
        sched_yield();
        n++;

        pthread_mutex_lock(&mutex_t);
        cout << " Thread 1: "<< n<<endl;
        pthread_mutex_unlock(&mutex_t);
    }

    pthread_mutex_lock(&mutex_t);
    cout << "canceling thread...\n" <<endl;
    pthread_mutex_unlock(&mutex_t);

    if (pthread_cancel(thread_id) == 0)
    {
        //This doesn't wait for the thread to exit
        pthread_mutex_lock(&mutex_t);
        cout << "detaching thread...\n"<<endl;
        pthread_mutex_unlock(&mutex_t);

        pthread_detach(thread_id);

        while (pthread_kill(thread_id,0)==0)
        {
                sched_yield();
        }

        pthread_mutex_lock(&mutex_t);
        cout << "thread is canceled";
        pthread_mutex_unlock(&mutex_t);

    }

    pthread_mutex_lock(&mutex_t);
    cout << "exit"<<endl;
    pthread_mutex_unlock(&mutex_t);

    return 0;
}

Cuando se sustituye la Cout con printf () i workes hasta el final "salida", pero con el cout (incluso bloqueado) cuelga ejecutables después de la salida de "hilo separar ...

Sería muy bueno saber de un favorable, cuál es el problema aquí es ?. ¿Por qué esto no funciona incluso cuando cout está bloqueado por un mutex!?

¿Fue útil?

Solución

LA probelm radica en que COUT tiene un punto de cancelación implícita!

Necesitamos código como este:

pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
    pthread_testcancel();
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);

y hacer que el hilo al principio:

pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);

Esto asegura que sólo pthread_cancel () tiene un punto de cancelación ...

Otros consejos

Trate comentando la línea de pthread_detach(thread_id); y ejecutarlo. Que está creando el hilo como independiente con su pthread_attr_t.

O eso, o tratar de pasar NULL en lugar de attr y en el pthread_create (de modo que el hilo es no creados independiente) y ejecutarlo.

Me imagino que si es el momento adecuado, el (ya separada) hilo se ha ido para el momento en que el hilo principal intenta la pthread_detach, y va apagado en Nunca Jamás en pthread_detach.

Editar:

Si cout tiene un punto de cancelación implícita como señala Gabriel cabo, lo más probable es lo que sucede es que el hilo se cancela mientras se mantiene la exclusión mutua (que nunca llega al pthreads_unlock_mutex después de que el cout), por lo que cualquier otra persona que espera en el mutex se ser bloqueado para siempre.

Si el único recurso que tiene que preocuparse es el mutex, se podría realizar un seguimiento de si su mensaje ha es bloqueada y luego desbloquearlo en la limpieza, en el supuesto de que la limpieza se ejecuta en el mismo hilo.

Tome un vistazo aquí, en la página 157 en: PThreads Primer .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top