1

Eclispse Indigo + CDT 8.0.2 + cygwin を使用して、マルチスレッド systerm を開発しました。コードは以下のとおりです。

pthread_mutex_t mutexCmd = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t signalCmd = PTHREAD_COND_INITIALIZER;

void * Func(void * arg)
{
    int iStatus;
    while (1)
    {
        int a = 1;
        pthread_cleanup_push(pthread_mutex_unlock, &mutexCmd);
        pthread_mutex_lock(&mutexCmd);
        iStatus = pthread_cond_wait(&signalCmd, &mutexCmd);
        if (iStatus) {
                err_abort(iStatus, "signalCmd status error");
        }
        if(arg->Cmd != navi_Go) //Just a command tag;
        {
            pthread_mutex_unlock(&(pNaviCtrl->mutexCmd));
            continue;
        }
        //do some work
        //.....
        pthread_mutex_unlock(&mutexCmd);
        pthread_cleanup_pop(1);
    }
//pthread_detach(pthread_self());
return  NULL;
}

int main()
{
    int iStatus = 0;
    pthread = tid;
     iStatus = pthread_create(&tid;NULL, Func, NULL);
     if(iStatus)
    {
    err_abort(iStatus, "Start pthread error");
    }
    // do some work
    ...
    //Cancel thread
   void * retval;
   iStatus = pthread_cancel(tid) 
   iStatus = pthread_join(tid; &retval);
   if(iStatus){
        err_abort(iStatus,"Stop thread error");
    }
    return iStatus;
}

プログラムが実行されると、「iStatus = pthread_join(tid1; &retval);」で停止します。スレッドがデッドロックに陥った可能性があると思いますが、理由が見つかりません。pthread_cancel() を呼び出した後、スレッドは終了して pthread_join() に戻ると思いましたが、私のコードの何が問題なのか誰に教えてもらえますか?

4

2 に答える 2

1

pthread_cleanup_pop(1)スタックからクリーンアップ エントリをポップするだけでなく、それを実行するように pthread ライブラリに指示します。したがって、その呼び出しは暗黙的に次の呼び出しも行います。

pthread_mutex_unlock(&mutexCmd);

既にミューテックスのロックを解除しているため、その呼び出しの動作は未定義です (ミューテックスのタイプが であると仮定しますPTHREAD_MUTEX_NORMAL)。その電話は決して戻ってこないか何かだと思います。

コードには、クリーンアップの処理に関する他の問題があることに注意してください。forcontinueループを実行するとpthread_cleanup_push()、2 回目 (またはそれ以上) を呼び出すことになり、別のクリーンアップ コンテキストが追加されます。

他の問題があるかもしれません (私はあまり詳しくありませんpthread_cancel())。

于 2012-05-09T21:34:32.317 に答える
1

while ループ内に cleanup_push と _pop を入れないでください。それらを複数回呼び出さないでください。それらを見ると、コードを { } で囲んでいるマクロです。pthread_cancel を呼び出すときに使用される longjump をセットアップします。

于 2012-05-10T01:57:12.293 に答える