2011-08-04 1 views
1

g ++バージョン4.4.3(Ubuntu 4.4.3-4ubuntu5)とlibpthread v。2-11-1を使用しています。次のコードは、単にFoo()を実行中のスレッドを作成し、すぐにそれを取り消しますスレッドを連続して作成したりキャンセルしたりするときの奇妙な動作

void* Foo(void*){ 
    printf("Foo\n"); 
    /* wait 1 second, e.g. using nanosleep() */ 

    return NULL; 
} 

int main(){ 
    pthread_t thread; 

    int res_create, res_cancel; 
    printf("creating thread\n); 
    res_create = pthread_create(&thread, NULL, &Foo, NULL); 
    res_cancel = pthread_cancel(thread); 
    printf("cancelled thread\n); 
    printf("create: %d, cancel: %d\n", res_create, res_cancel); 

    return 0; 
} 

私が手出力は次のようになります。

creating thread 
Foo 
Foo 
cancelled thread 
create: 0, cancel: 0 

なぜ二Foo出力? をpthread_createの直後に呼び出してpthread APIを悪用していますか?もしそうなら、どのようにスレッドに触れることが安全であるかを私は知ることができますか?もし私がprintf()を2つの間に張っているのであれば、私はこの問題はありません。

+0

MacOS 10.6.8で試してみました。 – Saphrosit

答えて

0

これは若干新しいUbuntuで再現できません。時々私はFooとときどき1つを得る。私は、問題を再現した実際のコードを貼り付けなかったことを示すために、コードをコンパイルするためにいくつかの問題を修正しなければなりませんでした(ヘッダーの欠落、コメントと文字列リテラルが閉じていないいくつかのスリープ関数の呼び出しがありません)。

問題が本当に本当の場合は、glibcのIOライブラリでスレッドキャンセルの問題が発生している可能性があります。同じバッファの内容でflush(stdout)を実行する2つのスレッドのように見えます。 IOライブラリがスレッドセーフなので、これは決して正常に行われるべきではありません。しかし、スレッドがmutexをstdoutに持っていて、フラッシュを完了しただけで、まだバッファを更新して出力をクリアしていないなどのキャンセルシナリオがあるとしたらどうでしょうか?そして、それができる前にキャンセルされ、メインスレッドは同じデータを再びフラッシュします。