简单分离的 pthread 不会取消! (即使互斥,cout 也会块和交错)

发布于 2024-08-25 01:00:12 字数 2683 浏览 7 评论 0原文

我这里有一个难题,我无法解决,也没有在网上找到正确的答案:

我创建了一个带有清理路由的独立线程,问题出在我的 Imac 和 Ubuntu 9.1(双核)上。我无法正确取消以下代码中的分离线程:

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

当我用 printf() 替换 Cout 时,我工作到最后“exit”,但使用 cout(甚至锁定),可执行文件在输出“分离线程”后挂起。 ..

如果能从专业人士那里知道问题出在哪里,那就太酷了。 为什么即使 cout 被互斥锁锁定也不起作用!?

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!?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

平安喜乐 2024-09-01 01:00:12

问题在于 COUT 有一个隐式取消点!

我们需要这样编写代码:

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

并在开头创建线程:

pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);

这确保只有 pthread_cancel() 有取消点...

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...

有深☉意 2024-09-01 01:00:12

尝试注释掉 pthread_detach(thread_id); 行并运行它。您正在创建与 pthread_attr_t 分离的线程。

或者尝试在 pthread_create 中传递 NULL 而不是 &attr (这样线程就不会被分离创建)并运行它。

我猜想,如果时机正确,(已经分离的)线程在主线程尝试 pthread_detach 时就消失了,并且您将进入 pthread_detach 中的梦幻岛。

编辑:

如果 cout 有一个隐式取消点,正如 Gabriel 指出的那样,那么最有可能发生的情况是线程在持有互斥体时取消(它永远不会在 cout 之后进入 pthreads_unlock_mutex),因此等待互斥体的其他人将被永远被封锁。

如果您需要担心的唯一资源是互斥体,则可以跟踪您的线程是否已锁定它,然后在清理中解锁它,假设清理在同一线程中运行。

请查看此处,第 157 页:PThreads Primer< /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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文