マルチスレッドの競合状態のテスト


54

この回答へのコメントを読む、具体的には:

テストを書くことができないからといって、テストが壊れていないわけではありません。通常、期待どおりに動作する未定義の動作(CおよびC ++はそのすべてで満たされています)、競合状態、メモリモデルの弱さによる潜在的な再配列... – CodesInChaos 7時間前

@CodesInChaos再現できない場合、「修正」に書き込まれたコードもテストできません。未テストのコードを公開することは、私の意見では最悪の犯罪です– RhysW 5時間前

...テストケースの競合状態が原因で、本番環境で非常にまれにしか発生しない問題を一貫して引き起こす良い一般的な方法があるかどうか疑問に思っています。


1
(アセンブリ)命令をステップごとに実行します
ラチェットフリーク

1
静的分析では、潜在的なUBが示されることがよくありますが、これがテストとしてカウントされるかどうかは明らかではありません
jk。

質問して申し訳ありませんが、「UB」とはどういう意味ですか?
ダグ

2
いい質問です、これに対する潜在的な解決策を見るのは面白いでしょう。
-RhysW

1
@Doug Undefined Behaviour。これには、競合状態
jk)

回答:


85

1978年頃からこのクレイジーなビジネスに携わった後、ほとんどすべての時間を組み込みリアルタイムコンピューティングに費やし、マルチタスク、マルチスレッド、マルチwhateverシステム、時には複数の物理プロセッサを使用して、私の公平なシェアを追いました条件については、あなたの質問への答えは非常に簡単であるという私の考えの意見です。

番号。

テストで競合状態を引き起こす良い一般的な方法はありません。

あなたの唯一の望みは、あなたのシステムから完全にそれらを設計することです。

誰かが誰かを詰め込んだことがわかった場合は、彼を蟻塚から外に出して、それを排除するように再設計する必要があります。システムから彼のフェイクパス(f *** upと発音)を設計したら、アリから彼を解放することができます。(もしアリがすでに骨を残して彼を消費しているなら、「これはXYZプロジェクトに競争条件を入れた人々に何が起こるか!」と言って、そこに彼を置いてください。)


22
同意します。言い換えれば、これは冗談によく似ています-患者:「医師、これをやると痛い...」医師:「やめろ!」
マークラシャコフ

素敵な答え。何かがテスト不能な問題を引き起こす場合は、そもそもその問題を回避してみて、問題を完全に回避してください!
RhysW

私の唯一の質問は、どのくらいの蟻塚を使用すればよいですか?(+1 BTW)。
ピーターK.

15
フェイクパスの正しい発音のために+1 。(そして残りの答え。)
Blrfl

1
@PeterKは、これは大きなを監視し、RAM、およびディスクドライブ、と一緒に、ソフトウェア開発におけるそれらのいくつかの例1であるISより良いです。
ジョンR.ストローム14

16

msツールチェーンにいる場合。Msの研究では、実行ごとに新しい相互関連を強制し、チェスと呼ばれる失敗した実行を再作成できるツールを作成しました。

ここにあるビデオの使用でそれを示したが。


5
それは印象的です。いつか試してみる時間を見つける必要があります。
ダン・ニーリー

16

この種の問題について私が知っている最良のツールは、Helgrindと呼ばれるValgrindの拡張です。

基本的にValgrindは仮想プロセッサをシミュレートし、その上でバイナリ(変更なし)を実行するため、メモリへのすべてのアクセスを確認できます。Helgrindウォッチシステムは、そのフレームワークを使用して、共有変数へのアクセスが相互排除メカニズムによって適切に保護されていない場合に推論するために呼び出します。そうすれば、実際に発生していなくても理論的な競合状態を検出できます。

IntelはIntel Inspectorと呼ばれる非常によく似たツールを販売しています。

これらのツールは優れた結果をもたらしますが、分析中のプログラムはかなり遅くなります。


1
Valgrindはまだ* nix専用のツールですか?
ダンニーリー

1
はい、Linux、MacOSX、Android、およびいくつかのBSD:valgrind.org/info/platforms.html
Julien

1
ThreadSanitizerも同様のツールです。Helgrindとは動作が異なり、はるかに高速であるという利点がありますが、ツールチェーンへの統合が必要です。
セバスチャンレッド

7

マルチスレッドのバグを公開するには、異なる実行スレッドに特定のインターリーブされた順序でステップを実行させる必要があります。通常、これは、手動でデバッグしたり、このインターリーブを制御するための何らかの「ハンドル」を取得するためにコードを操作したりすることなく行うのは困難です。しかし、予測できない動作をするコードを変更すると、その予測不能性に影響を与えることが多いため、これを自動化するのは困難です。

実用的なAPI設計でJaroslav Tulachが素晴らしいトリックを説明しています。問題のコードにロギングステートメントがある場合、それらのロギングステートメントの消費者(たとえば、挿入された疑似端末)を操作して、特定のログメッセージを受け入れるようにしますコンテンツに基づいて注文します。これにより、異なるスレッドでのステップのインターリーブを制御できます。まだ存在していない本番コードに何かを追加する必要はありません。


2
挿入されたリポジトリを使用して特定の順序で呼び出すスレッドをスリープさせ、必要なインターリーブを強制する前に、同様のことを行いました。それを行うコードを書いたので、私は上記の@Johnの答えを+1したいと思っています。真剣に、このようなものを正しく使用するのは非常に苦痛であり、結果が異なるわずかに異なるインターリーブが存在する可能性があるため、依然として最良の推測保証のみを提供します。より良いアプローチは、単に静的解析や、または任意のコードを慎重にコーミングし、すべての共有状態を介してすべての可能な競合状態排除することである
ジミー・ホッファ

6

さまざまな種類の未定義の動作(特定の競合状態)が存在しないことを絶対に確認する方法はありません。

ただし、このような状況を適切に表示するツールは多数あります。修正が有効であることを証明できなくても、現在そのようなツールに問題があることを証明できる場合があります。

この目的のためのいくつかの興味深いツール:

Valgrindはメモリチェッカーです。メモリリーク、未初期化メモリの読み取り、ダングリングポインターの使用、および範囲外アクセスを検出します。

Helgrindは、スレッドセーフティチェッカーです。競合状態を見つけます。

両方とも動的なインスツルメンテーションによって機能します。つまり、プログラムをそのまま使用し、仮想化環境で実行します。これにより、邪魔になりませんが、時間がかかります。

UBSanは未定義の動作チェッカーです。整数のオーバーフロー、範囲外のシフトなど、CおよびC ++の未定義の動作のさまざまなケースを検出します。

MSanはメモリチェッカーです。Valgrindと同様の目標があります。

TSanはスレッドセーフティチェッカーです。Helgrindと同様の目標があります。

これら3つはClangコンパイラに組み込まれ、コンパイル時にコードを生成します。これは、それらをビルドプロセスに統合する必要があることを意味します(特に、Clangでコンパイルする必要があります)。これにより、* grindよりも初期セットアップがはるかに難しくなりますが、一方で、ランタイムオーバーヘッドははるかに低くなります。

リストしたツールはすべてLinux上で動作し、一部はMacOS上で動作します。私はまだWindowsで確実に動作するとは思わない。


1

ここでの回答のほとんどは、この質問を「競合状態を自動的に検出する方法」と誤解しているようです。質問が本当に「テスト時に競合状態を見つけたときに再現するにはどうすればよいですか」

それを行う方法は、テストにのみ使用されるコードに同期を導入することです。たとえば、イベントAとイベントBの間にイベントXが発生したときに競合状態が発生した場合、アプリケーションをテストするために、イベントAの発生後にイベントXが発生するのを待つコードを記述します。テストでアプリケーションと通信して、それを伝えるための何らかの方法が必要になる可能性があります(「このことをテストしているので、この場所でこのイベントを待ってください」)。

node.jsとmongoを使用しています。いくつかのアクションでは、複数のコレクションに一貫したデータを作成する必要があります。これらの場合、ユニットテストはアプリケーションを呼び出して「イベントXの待機を設定する」ことを通知し、アプリケーションがセットアップすると、イベントXのテストが実行され、その後テストが通知しますアプリケーション(「イベントXの待機が完了しました」)であるため、残りのテストは正常に実行されます。

ここでの答えは、Pythonのコンテキストでこのタイプのことを詳細に説明しています:https : //stackoverflow.com/questions/19602535/how-can-i-reproduce-the-race-conditions-in-this-python-code-確実に

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.