2017-11-18 13 views
0

私はジョブをキューに追加しているプロジェクトがあります。ジョブを取得し、独自の独立した結果を計算する複数のスレッドがあります。pthread_joinでスレッドが停止するのを止めるにはどうしたらいいですか?

私のプログラムはSIGINTシグナルを処理しますが、スレッドに参加して結果を追加し、画面に出力して終了します。私の問題は、シグナルを送信するときにスレッドが機能しなくなったように見えるか、mutex_lockでブロックされてしまうことです。ここで私のプログラムの重要な部分が簡潔になるようにしています。あなたの助けのための

main.cの

//the thread pool has a queue of jobs inside 
//called jobs (which is a struct) 
struct thread_pool * pool; 

void signal_handler(int signo) { 
    pool->jobs->running = 0; //stop the thread pool 
    pthread_cond_broadcast(pool->jobs->cond); 

    for (i = 0; i < tpool->thread_count; i++) { 
     pthread_join(tpool->threads[i], retval); 
     //do stuff with retval 
    } 

    //print results then exit 
    exit(EXIT_SUCCESS); 
} 

int main() { 
    signal(SIGINT, signal_handler); 
    //set up threadpool and jobpool 
    //start threads (they all run the workerThread function) 
    while (1) { 
     //send jobs to the job pool 
    } 
    return 0; 
} 

void add_job(struct jobs * j) { 
    if (j->running) { 
     pthread_mutex_lock(j->mutex); 
     //add job to queue and update count and empty 
     pthread_cond_signal(j->cond); 
     pthread_mutex_unlock(j->mutex); 
    } 
} 

struct job * get_job(struct jobs * j) { 

    pthread_mutex_lock(j->mutex); 

    while (j->running && j->empty) 
     pthread_cond_wait(j->cond, j->mutex); 

    if (!j->running || j->empty) return NULL; 

    //get the next job from the queue 
    //unlock mutex and send a signal to other threads 
    //waiting on the condition 
    pthread_cond_signal(j->cond); 
    pthread_mutex_unlock(j->mutex); 
    //return new job 
} 

void * workerThread(void * arg) { 
    struct jobs * j = (struct jobs *) arg; 
    int results = 0; 
    while (j->running) { 
     //get next job and process results 
    } 
    return results; 
} 

thread_stuff.cおかげで、これは私の本当の頭痛の種を与えています!

+0

[このPOSIX信号の概念のリファレンス](http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04)を読むと、セクション2.4.3の最後にリストが表示されます* async-safe *である関数のため、シグナルハンドラから安全に使用できます。そのリストを見ると、['pthread_join](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html)が*表示されません。つまり、シグナルハンドラで呼び出すべきではありません。 –

答えて

2

SIGINTのように非同期に生成された信号を処理するシグナルハンドラからは、pthread_cond_waitまたはpthread_joinをコールしないでください。代わりに、すべてのスレッドに対してSIGINTをブロックし、専用のスレッドを生成し、sigwaitを呼び出してください。つまり、SIGINT信号のシグナルハンドラコンテキスト外への到着を検出するため、async-signal-safe functionsに限定されません。シグナルがワーカー・スレッドの1つに渡された場合、自己デッドロックのリスクも回避します。

この時点で、作業キュー/スレッドプールを正常にシャットダウンするだけで済みます。詳細に応じて、runningフラグを使用する既存の方法は変更されない場合もあります。

+0

素晴らしい感謝!シャットダウンのためにget_job関数を終了するときに問題が発生しました。私はmutexのロックを解除していませんでした: ')なぜpthread_joinは非同期シグナルセーフな関数ではないのですか? – ImpendingShroom

+0

非常に少数の機能が非同期信号安全です。 'pthread_join'はリソースを解放する必要があり、POSIXは非同期シグナル安全メモリアロケータを必要としないので、ヒープを操作する関数は非同期シグナル安全ではありません。 –

+0

あなたのおかげで感謝します! – ImpendingShroom

関連する問題