4

Windowsアプリケーションでpthreadを使用しています。プログラムがデッドロックしていることに気づきました。簡単に調べたところ、次のことが発生したことがわかりました。

スレッド1がスレッド2を生成しました。スレッド2がスレッド3を生成しました。スレッド2は、ロック解除されていないスレッド3からのミューテックスを待機していました。

そこで、gdbでデバッグし、3番目のスレッドをバックトレースすると次のようになりました。

Thread 3 (thread 3456.0x880):
#0  0x7c8106e9 in KERNEL32!CreateThread ()
   from /cygdrive/c/WINDOWS/system32/kernel32.dll
Cannot access memory at address 0x131

どういうわけか、WindowsのCreateThread関数でスタック、デッドロックしました!明らかに、コードの実行を開始することさえできなかったとき、ミューテックスのロックを解除することはできませんでした。それでも、明らかにここでスタックしているという事実にもかかわらず、pthread_createはゼロ(成功)を返しました。

これを特に奇妙なものにしているのは、Linux上の同じアプリケーションにそのような問題がないことです。作成プロセス中にスレッドがハングする(!?)が、正しく作成されたかのように正常に戻る原因は、いったい何でしょうか。

編集:コードのリクエストに応じて、ここにいくつかのコードがあります(簡略化されています):

スレッドの作成:

if ( pthread_create( &h->lookahead->thread_handle, NULL, (void *)lookahead_thread, (void *)h->thread[h->param.i_threads] ) )
{
    log( LOG_ERROR, "failed to create lookahead thread\n");
    return ERROR;
}
while ( !h_lookahead->b_thread_active )
    usleep(100);
return SUCCESS;

b_thread_activeが設定されるまで待機することに注意してください。したがって、何らかの形でb_thread_activeが設定されているため、呼び出されるスレッドは何かを実行する必要があります...

...これがlookahead_thread関数です:

void lookahead_thread( mainstruct *h )
{
    h->lookahead->b_thread_active = 1;
    while( !h->lookahead->b_exit_thread && h->lookahead->b_thread_active )
    {
        if ( synch_frame_list_get_size( &h->lookahead->next ) > delay )
            _lookahead_slicetype_decide (h);
        else
            usleep(100);  // Arbitrary number to keep thread from spinning
    }
    while ( synch_frame_list_get_size( &h->lookahead->next ) )
        _lookahead_slicetype_decide (h);
    h->lookahead->b_thread_active = 0;
}

lookahead_slicetype_decide(h); スレッドが行うことです。

ミューテックス、synch_frame_list_get_size:

int   synch_frame_list_get_size( synch_frame_list_t *slist )
{
    int fno = 0;

    pthread_mutex_lock( &slist->mutex );
    while (slist->list[fno]) fno++;
    pthread_mutex_unlock( &slist->mutex );
    return fno;
}

スレッド2のバックトレース:

Thread 2 (thread 332.0xf18):
#0  0x00478853 in pthread_mutex_lock ()
#1  0x004362e8 in synch_frame_list_get_size (slist=0x3ef3a8)
    at common/frame.c:1078
#2  0x004399e0 in lookahead_thread (h=0xd33150)
    at encoder/lookahead.c:288
#3  0x0047c5ed in ptw32_threadStart@4 ()
#4  0x77c3a3b0 in msvcrt!_endthreadex ()
   from /cygdrive/c/WINDOWS/system32/msvcrt.dll
#5  0x7c80b713 in KERNEL32!GetModuleFileNameA ()
   from /cygdrive/c/WINDOWS/system32/kernel32.dll
#6  0x00000000 in ?? 
4

1 に答える 1

1

スレッド 2 とスレッド 3 でミューテックスを再確認してみます。Pthreads は、標準の Windows API を使用して Windows 用に実装されています。そのため、Windows と Linux のバージョンにはわずかな違いがあります。これは奇妙な問題ですが、繰り返しになりますが、これはスレッド化でよく発生します。

ロックがスレッド 2 で行われ、スレッド 3 が開始される関数でコードのスニペットを投稿してみてください。

コードに応じて編集する

スレッド 2 でミューテックスのロックを解除したことがありますか? トレースは、ミューテックスをロックし、ミューテックスもロックしようとするすべての作業を行うスレッドを作成することを示しています。スレッド2がSUCESSを返した後だと思いますか?また、なぜフラグとスリープを使用しているのか、おそらくプロセス同期のためのバリアまたは条件変数がより堅牢になる可能性があります。

別の注意として、b_thread_active フラグは揮発性としてマークされていますか? おそらく、コンパイラは何かをキャッシュして、それが発生しないようにしていますか?

于 2009-02-19T21:45:20.363 に答える