Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Cancel Safetyとスレッドリーク
Search
garasubo
July 24, 2024
1
610
Cancel Safetyとスレッドリーク
garasubo
July 24, 2024
Tweet
Share
More Decks by garasubo
See All by garasubo
RustでISUCONに勝つには
garasubo
1
740
Rustでの自作OSをやってきて
garasubo
0
1.1k
Armの仮想化支援機構を用いてハイパーバイザーを自作する
garasubo
3
7.3k
RustからX Window Systemを触る
garasubo
0
660
Rustで始める自作組込みOS
garasubo
1
3.5k
クラウド向けOS(?)Unikernelとは何か
garasubo
0
1.8k
論文紹介:KVM/ARM: The Design and Implementation of the Linux ARM Hypervisor
garasubo
0
640
Featured
See All Featured
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
7.8k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
51k
The Language of Interfaces
destraynor
162
25k
What's in a price? How to price your products and services
michaelherold
246
12k
For a Future-Friendly Web
brad_frost
180
10k
Raft: Consensus for Rubyists
vanstee
141
7.2k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
Designing Experiences People Love
moore
143
24k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.4k
Context Engineering - Making Every Token Count
addyosmani
9
490
The Invisible Side of Design
smashingmag
302
51k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
1
93
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コンパイラでも保証しきれない性質がたくさんある • ドキュメントをきちんと読んで非同期プログラミングの仕組みを理解しよう • テスト・監視など他のプログラミング言語でも有用な当たり前のことをしましょう