Semplice pthread indipendente non cancella! (Blocchi cout e intercalari anche se mutexed)

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

  •  19-09-2019
  •  | 
  •  

Domanda

Ho un problema difficile qui, che non riesco a risolvere e non trovare la risposta giusta in rete:

Ho creato un filo staccato con un instradamento pulizia, il problema è che sul mio iMac e Ubuntu 9.1 (Dual Core). Io non sono in grado di annullare correttamente il filo staccato nel codice maggese:

#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;
}

Quando si sostituisce la Cout con printf () i Workes fino alla fine "uscita", ma con il cout (anche bloccato) si blocca l'eseguibile dopo output "filo distacco ...

Sarebbe molto bello sapere da un Pro, qual è il problema qui è ?. Perché questo non funziona anche quando cout è bloccato da un mutex!?

È stato utile?

Soluzione

IL problema soltanto risiede in quel COUT ha un punto di cancellazione implicita!

Abbiamo bisogno di codice come questo:

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

e fare il filo all'inizio:

pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);

che garantisce che solo pthread_cancel () ha un punto di cancellazione ...

Altri suggerimenti

Provare a commentare la linea di pthread_detach(thread_id); ed eseguirlo. Si sta creando il filo come indipendente con il vostro pthread_attr_t.

O che, o cercare passando NULL anziché & attr nel pthread_create (in modo che il filo è non creato distaccato) ed eseguirlo.

Direi che se il momento è giusto, il (già monofamiliare) filo è andato per il momento il thread principale tenta il pthread_detach, e si sta andando fuori in Never Never Land in pthread_detach.

Modifica:

Se cout ha un punto di cancellazione implicita come sottolinea Gabriel fuori, quindi molto probabilmente ciò che accade è che il filo annulla mentre si tiene il mutex (non è mai lo rende al pthreads_unlock_mutex dopo il cout), e così chiunque altro in attesa sul mutex sarà essere bloccato per sempre.

Se l'unica risorsa che dovete preoccupare è il mutex, si potrebbe tenere traccia di se o non è il tuo thread è esso bloccato e poi sbloccarlo nella pulizia, partendo dal presupposto che la pulizia viene eseguito nello stesso thread.

Date un'occhiata qui, pagina 157 sopra: pthread Primer .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top