1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[LT] Thread Sanitizer

Last updated at Posted at 2017-04-12

チーム全体、毎週金曜日の朝、一人3分 LT をやっています。忘れないように、また日本語の勉強もしたいと思います、記事として記録します。

最近はプロジェクトの改善をしています、テストコードの補足とスレッド管理の増強に注目しています。スレッド問題は発生する時、そもそもタイミングに敏感ですが、再現しにくい、デバッグも難しい、本当に忘れられない体験になると思います。。。WWDC 2016(Session 412) で公開されました機能ーーThread Sanitizer を使い始めましょう。この機能は Xcode に統合されています、略称は TSan です。

TSan を有効にすると:

Use of uninitialized mutexes
Thread leaks (missing pthred_join)
Unsafe calls in signal handlers (ex:malloc)
Unlock from wrong thread
Data races

以上の問題を全て発見できます。一番発生しやすい **Data races(データ競合)**を展開したい、データ競合の発生原因は同期ではない場合、複数のスレッドから同じメモリをアクセスする時、少なくとも一つのアクセスで write 操作を行っています。実際の運用中、表現としては:データの不整合、アプリのクラッシュなど。

最近改善中のアプリを例に:

[context performBlock:^{
    if (result && context) {
        result = [self persistentSaveContext:context]; // 1
    }
}];
return result; // 2

result は 1 と 2 二箇所で競合してしまう。1 で write 操作を行いながら、別スレッドの 2 はすでに戻す可能性があるので、データ不整合になるかもしれません。

修正方法はいくつかあります、非同期から同期に変更するとか、write 操作の実行タイミングを変更するとか。ここで、非同期メソッドの performBlock を使わずに、同じ用途の同期メソッド performBlockAndWait を使いました。そうすると、データ競合が解決されました。

[context performBlockAndWait:^{
    if (result && context) {
        result = [self persistentSaveContext:context]; // 1
    }
}];
return result; // 2

実に Thread Sanitizer 機能はコンパイラ (Clang) レベルで統合されます、そのため、もし Swift でサーバーサイドを書くときにもコマンドラインで Thread Sanitizer を使えます:

st1.png

現在、64bit シミュレーターまたは macOS 自体のみ Thread Sanitizer をサポートできますが、かなり素晴らしい機能だと思います。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?