Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Cancel Safetyとスレッドリーク
Search
garasubo
July 24, 2024
1
430
Cancel Safetyとスレッドリーク
garasubo
July 24, 2024
Tweet
Share
More Decks by garasubo
See All by garasubo
RustでISUCONに勝つには
garasubo
1
640
Rustでの自作OSをやってきて
garasubo
0
1k
Armの仮想化支援機構を用いてハイパーバイザーを自作する
garasubo
3
7k
RustからX Window Systemを触る
garasubo
0
620
Rustで始める自作組込みOS
garasubo
1
3.4k
クラウド向けOS(?)Unikernelとは何か
garasubo
0
1.7k
論文紹介:KVM/ARM: The Design and Implementation of the Linux ARM Hypervisor
garasubo
0
570
Featured
See All Featured
Gamification - CAS2011
davidbonilla
80
5.1k
For a Future-Friendly Web
brad_frost
176
9.5k
How STYLIGHT went responsive
nonsquared
98
5.4k
A Tale of Four Properties
chriscoyier
158
23k
Rails Girls Zürich Keynote
gr2m
94
13k
Designing for humans not robots
tammielis
250
25k
Large-scale JavaScript Application Architecture
addyosmani
511
110k
We Have a Design System, Now What?
morganepeng
51
7.4k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
193
16k
Building an army of robots
kneath
303
45k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.1k
Designing for Performance
lara
604
68k
Transcript
Cancel Safetyと スレッドリーク Rustでも怖い非同期プログラミング
自己紹介 • ハンドルネーム:ガラスボー(@garasubo) • 現在はIdein株式会社に所属 – IoTプラットフォームの開発を担当 – RustをサーバーサイドやIoT端末上で利用 –
エンジニア以外も積極採用中なので興味があれば採用ページを
Cancel Safetyとスレッドリーク • Rustでの非同期プログラミングのおさらい • tokio::selectとcancel safety • プロダクションで起きたスレッドリーク事件
Rustでの非同期プログラミング
Rustでの非同期プログラミング async/.await構文登場以前だと非同期処理の扱いは デファクトがなくライブラリも乱立状態 async/.await構文登場以降はtokioをランタイムとして利用した async/.awaitを使った非同期プログラミングが主流に
tokioとは • Rustの汎用非同期ランタイム • async/.await構文を利用するには何かしらの非同期ランタイムが必要 – スレッド管理やスケジューリングの仕方をカスタマイズできるようにするため – Rustのstd側での提供はなく、よく使われるのがtokio –
詳しい仕組みはAsync Programming in Rustなどを参照 • 多くの非同期処理が絡むライブラリもtokioに依存している場合が多い
tokio::selectと cancel safety
tokio::select • 複数のasync関数を同時に実行して先に終了した方の結果を返すマクロ • 選ばれなかった方のfutureはcancelされて結果が破棄される 選ばれなかった場合のことを考えて、途中で終了しても困らないような関数の みを呼び出す必要がある
tokio::select
Cancel Safety 途中で終了してもデータが欠損したりせず困らないという性質 Cancel Safeでない例: tokio::io::AsyncReadExt::read_exact • 指定されたバッファの長さを全部埋めるまでデータを読み込む • キャンセルされるとバッファにある程度データを取り込んだ状態になるため、途中まで
取り込んだデータが失われてしまう tokioの関数であればcancel safeなものはcancel safeだと書いてあるので ドキュメントを読みましょう
Cancel Safeの見極め方 asyncな関数はawaitが呼び出される箇所でのみ中断される可能性がある async中のあらゆるawaitポイントで実行が止まっても内部状態が失われないこと この性質は型としては表現されないのでコンパイルエラーにはならない
プロダクションで起きた スレッドリーク事件
スレッドリーク事件 右のようなコードを書いたところスレッドが 無限に生成されてプログラムがスタックした
スレッドリーク事件 tokio::selectが呼び出され、 waitとwait2のうちどちらかを待つ wait2が先に終わるとループが続 行し、再びtokio::selectでwait とwait2のどちらかを待つ
スレッドリーク事件 waitは通常だと終了しない処理 (今回は無限ループでスリープ) wait2は比較的短い処理なので通 常ならばwait2の方が先に終了する
スレッドリーク事件 wait2が終わる task内のループが再び実行 waitが呼び出されスレッドが 作られる wait2が終わり再びループへ
スレッドリーク事件 よく見ると無限ループ内にawaitがない つまりcancelしたくてもそもそも中断が できない状態 呼び出されるたびに 中断できないスレッドが溜まっていく
教訓 • 非同期プログラミングではRustコンパイラでも保証しきれない性質がたくさんある • ドキュメントをきちんと読んで非同期プログラミングの仕組みを理解しよう • テスト・監視など他のプログラミング言語でも有用な当たり前のことをしましょう