2
gcc (GCC) 4.6.3
valgrind-3.6.1

送受信用の2つの異なるスレッドでいくつかのメッセージを送受信するアプリケーションを作成しました。ロックにpthread、条件変数、ミューテックスを使用します。

ただし、送信者はメッセージを送信し、受信者にメッセージを受信して​​処理するように通知します。これはwhileループで行われます。

ただし、ctrl-cを使用してアプリケーションを終了し、割り込みを処理すると、問題が発生します。送信されているメッセージがない場合、受信者は受信を待機しているwhileループでスタックします。

メインスレッドはjoinを呼び出し、レシーバーが終了するのを待ってブロックします。しかし、それは待っているほどではありませんpthread_cond_wait

pthread_cancelまたはを使用することを考えていましたpthread_kill。しかし、それはスレッドが正常に終了することを許可しないので、私はそれをするのが好きではありません。

提案をありがとう。

主な機能

    void main(void)
    {
        /* Do some stuff here */

    /* Start thread that will send a message */
    if(pthread_create(&thread_recv_id, &thread_attr, thread_recv_fd, NULL) == -1) {
        fprintf(stderr, "Failed to create thread, reason [ %s ]",
            strerror(errno));
            break;
        }
        printf("Start listening for receiving data'\n");

        /* Start thread to receive messages */
        if(pthread_create(&thread_send_id, &thread_attr, thread_send_fd, NULL) == -1) {
            fprintf(stderr, "Failed to create thread for receiving, reason [ %s ]",
                    strerror(errno));
            break;
        }

    /* Clean up threading properties */
    pthread_join(thread_send_id, NULL);
    pthread_join(thread_recv_id, NULL); <---- blocking here waiting for the recv thread to finish

    pthread_mutex_destroy(&mutex_queue);
    pthread_cond_destroy(&cond_queue);

    return 0;
}

送信者スレッド

void *thread_send_fd()
{
        pthread_mutex_lock(&mutex_queue);
        if(send_fd((int)fd) == FALSE) {
            /* Just continue to send another item */
            continue;
        }
        /* Signal the waiting thread to remove the item that has been sent */
        pthread_cond_signal(&cond_queue);

        pthread_mutex_unlock(&mutex_queue);
}

レシーバースレッド

void *thread_recv_fd()
{
    while(is_receiving()) {
        pthread_mutex_lock(&mutex_queue);

        /* Wait for an item to be sent on the queue */
        pthread_cond_wait(&cond_queue, &mutex_queue); <---- waiting here

        queue_remove();
        pthread_mutex_unlock(&mutex_queue);
    }

    pthread_exit(NULL);
}
4

1 に答える 1

9

基本的に3つの選択肢があります。

  1. を使用しpthread_cancelます。pthread_cond_waitこれにより、呼び出しが中断されてからスレッドが終了pthread_cleanup_pushし、途中でに登録されているキャンセルハンドラーが呼び出されます。

  2. スレッドにシグナルを送信するために使用pthread_killします。これはスレッドを「殺す」のではなく、シグナルを送信するだけです。この場合、使用するシグナルのシグナルハンドラーをそのスレッドに登録しておく必要があり、そのシグナルハンドラーは、スレッドに終了するように指示するために何かを実行する必要があります。シグナルハンドラーはループを終了させるために何かをする必要があるため、これは3番目のオプションよりも特に優れているわけではありません。pthread_cond_wait

  3. フラグを設定して条件変数を通知することを知っているスレッドに手動割り込み機能を追加します。次に、ループアラウンドpthread_cond_waitはフラグをチェックし、フラグが設定されている場合はスレッドを終了する必要があります。

(1)または(3)をお勧めします。使用は最も一般的ですが、スレッドによって割り当てられたすべてのリソースをクリーンアップしたり、すべてのミューテックスのロックを解除したりするためのpthread_cancel適切な呼び出しがあることを確認するために、スレッドで注意深く処理する必要があります。pthread_cleanup_push手動の中断機能を作成することは、より多くの作業になる可能性がありますが、アプリケーションに合わせて最も簡単に調整できます。

于 2012-04-12T08:09:05.917 に答える