tags:

views:

316

answers:

2

I have a hard problem here, which I can not solve and do not find the right answer on the net:

I have created a detached thread with a clean up routing, the problem is that on my Imac and Ubuntu 9.1 (Dual Core). I am not able to correctly cancel the detached thread in the fallowing code:

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

When I replace the Cout with printf() i workes to the end "exit" , but with the cout (even locked) the executable hangs after outputting "detaching thread...

It would be very cool to know from a Pro, what the problem here is?. Why does this not work even when cout is locked by a mutex!?

A: 

Try commenting out the line pthread_detach(thread_id); and run it. You are creating the thread as detached with your pthread_attr_t.

Either that, or try passing NULL instead of &attr in the pthread_create (so that the thread is not created detached) and run it.

I would guess that if the timing is right, the (already detached) thread is gone by the time the main thread attempts the pthread_detach, and you are going off into Never Never Land in pthread_detach.

Edit:

If cout has an implicit cancelation point as Gabriel points out, then most likely what happens is that the thread cancels while holding the mutex (it never makes it to pthreads_unlock_mutex after the cout), and so anybody else waiting on the mutex will be blocked forever.

If the only resource you need to worry about is the mutex, you could keep track of whether or not your thread has it locked and then unlock it in the cleanup, assuming that cleanup runs in the same thread.

Take a look here, page 157 on: PThreads Primer.

Jim Flood
I commented out the pthread_detach() (should not be a problem because it should give an error message back if thread is already cancelled)BUT the thing is when I run this programm here on Ubunutu 9.1. it hangs in -->while (pthread_kill(thread_id,0)==0) { sched_yield(); }BUT when I comment the <<endl; in cout << " Thread 2: "<< n<<endl;then every thing works fine, and it gets not stuck?but why??, I am sooo confused??Because of this cout? buffering? but its locked?
Gabriel
A: 

THE PROBELM lies in that COUT has a implicit cancelation point!

We need to code like this:

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

and make the thread at the beginning :

pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);

That ensures that only pthread_cancel() has a cancelation point...

Gabriel
Isn't it the case that the thread will ignore cancellation requests during the time that cancel is disabled?
Jim Flood
Yes, its the case, but because I got also problems without mutexes that cout blocked something because its not thread safe and my main thread got stuck, I decided to only allow cancelation between enable and disable :-)and it works very well....
Gabriel