2 poin oleh GN⁺ 2025-11-01 | Belum ada komentar. | Bagikan ke WhatsApp
  • Futurelock adalah fenomena deadlock yang terjadi ketika satu task mengelola beberapa Future sekaligus, lalu salah satunya membutuhkan resource milik Future lain tetapi tidak lagi di-poll
  • Mudah terjadi saat konstruksi tokio::select! menggunakan Future yang direferensikan (&mut future) bersama branch yang mengandung await
  • Masalah ini berasal dari gagalnya pemisahan tanggung jawab antara task dan Future, sehingga task yang sama menunggu dua Future tetapi hanya mem-poll salah satunya dan akhirnya berhenti total
  • Bentuk serupa juga bisa muncul pada FuturesUnordered, bounded channel, Stream, dan lainnya
  • Kunci desain asinkron yang aman adalah memisahkan Future ke task terpisah dengan tokio::spawn atau menghindari penggunaan await di dalam select

Konsep dan contoh Futurelock

  • Futurelock terjadi ketika Future A yang memegang resource dibutuhkan oleh Future B, tetapi task yang menangani keduanya tidak lagi mem-poll A
  • Pada kode contoh, tokio::select! menunggu &mut future1 dan sleep secara bersamaan; jika sleep selesai lebih dulu, future1 tetap berada dalam status menunggu lock
  • Setelah itu future3 meminta lock yang sama, tetapi lock sudah dialokasikan ke future1 dan future1 tidak dipoll lagi, sehingga program berhenti selamanya

Interaksi tokio::select! dan Mutex

  • tokio::sync::Mutex adalah lock yang fair, yaitu memberi lock sesuai urutan antrean
  • Lock diberikan kepada future1, tetapi task sudah hanya mem-poll future3, sehingga future1 tidak pernah berjalan
  • Mutex hanya bertugas membangunkan task penunggu berikutnya, dan tidak tahu Future mana yang benar-benar sedang dipoll

Penyebab umum Futurelock

  • Struktur dependensi melingkar ketika task T menunggu Future F1, F1 bergantung pada F2, dan F2 kembali membutuhkan polling dari T
  • Umumnya terjadi dalam situasi berikut
    • Menggunakan &mut future di tokio::select! lalu menjalankan await di branch lain
    • Pada FuturesOrdered atau FuturesUnordered, setelah sebagian Future selesai lalu melakukan pekerjaan asinkron lain
    • Perilaku serupa pada Future yang diimplementasikan secara manual

Kasus pada Stream dan struktur lain

  • Pada FuturesOrdered atau FuturesUnordered, Futurelock bisa terjadi setelah sebuah Future diambil lalu sistem menunggu Future lain yang memakai resource terkait
  • join_all tidak menimbulkan Futurelock karena terus mem-poll semua Future

Kasus nyata dan debugging

  • Dalam kasus Omicron#9259, semua Future akses database terkena Futurelock sehingga request HTTP menunggu tanpa batas
  • Pengiriman pada kanal mpsc terblokir, tetapi sisi penerima terlihat kosong sehingga penyebabnya sulit diidentifikasi
  • Saat debugging, alat seperti tokio-console dapat membantu, tetapi dalam banyak kasus pelacakan akar masalah sangat sulit

Pedoman pencegahan Futurelock

  • Saat satu task mem-poll beberapa Future, jangan sampai polling terhadap Future yang sudah dimulai dihentikan di tengah jalan
  • Jika memungkinkan, spawn Future sebagai task baru agar berjalan mandiri
    • Jika JoinHandle diteruskan ke tokio::select!, risiko Futurelock hilang
  • Hal yang perlu diperhatikan saat memakai tokio::select!
    • Jangan gunakan &mut future dan await secara bersamaan
    • Jika kedua kondisi itu ada sekaligus, risiko Futurelock menjadi tinggi
  • Saat memakai Stream, gunakan JoinSet untuk menjalankan tiap Future di task terpisah
  • Menambah kapasitas bounded channel bukan solusi mendasar
    • Sebagai gantinya, try_send() dapat dipakai untuk menghindari blocking

Pola penghindaran yang keliru

  • Menaikkan kapasitas channel tanpa batas tidak realistis dan menimbulkan efek samping seperti latensi dan penggunaan memori yang lebih besar
  • Mencoba menghilangkan dependensi antar-Future juga rapuh karena dependensi baru bisa muncul saat maintenance
  • Satu-satunya cara yang benar-benar aman adalah memisahkan task dengan tokio::spawn

Perbaikan ke depan dan pertimbangan keamanan

  • Ada kemungkinan menambahkan peringatan melalui lint Clippy saat tokio::select! memakai &mut future atau mengandung await
  • Futurelock bisa disalahgunakan sebagai bentuk penolakan layanan (DoS), tetapi pada dasarnya ini adalah perilaku abnormal sehingga perlu dicegah

Belum ada komentar.

Belum ada komentar.