Simple Detached pthread не отменяет! (блокирует и перемежает, даже если мьютекс) - PullRequest
2 голосов
/ 14 марта 2010

У меня здесь сложная проблема, которую я не могу решить и не могу найти правильный ответ в сети:

Я создал отдельный поток с маршрутизацией очистки, проблема в том, что на моих Imac и Ubuntu 9.1 (Dual Core). Я не могу правильно отменить отдельную ветку в следующем коде:

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

Когда я заменяю Cout на printf (), я работаю до конца "exit", но с cout (даже заблокированным) исполняемый файл зависает после вывода "отсоединения потока ...

Было бы очень круто узнать от профессионала, в чем здесь проблема? Почему это не работает, даже если cout заблокирован мьютексом??

Ответы [ 2 ]

2 голосов
/ 14 марта 2010

ПРОБЛЕМА заключается в том, что COUT имеет неявную точку отмены!

Нам нужно кодировать так:

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

и сделайте нить в начале:

pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);

Это гарантирует, что только pthread_cancel () имеет точку отмены ...

1 голос
/ 14 марта 2010

Попробуйте закомментировать строку pthread_detach(thread_id); и запустите ее.Вы создаете поток как отделенный с помощью pthread_attr_t.

Либо так, либо попробуйте передать NULL вместо & attr в pthread_create (чтобы поток не создавался отдельно), и запустите его.

Я бы предположил, что если время выбрано правильно, (уже отсоединенный) поток исчезнет к тому времени, когда основной поток попытается выполнить pthread_detach, и вы перейдете в Never Never Land в pthread_detach.

Редактировать:

Если cout имеет неявную точку отмены, как указывает Габриэль, то, скорее всего, произойдет то, что поток отменяет, удерживая мьютекс (он никогда не доберется до pthreads_unlock_mutex после cout), и таквсе, кто ожидает мьютекс, будут заблокированы навсегда.

Если единственный ресурс, о котором вам нужно беспокоиться, это мьютекс, вы можете отслеживать, заблокирован ли он в вашем потоке, а затем разблокировать его в процессе очистки., предполагая, что очистка выполняется в том же потоке.

Посмотрите здесь, стр. 157 на: PThreads Primer .

...