Section 11/161 menit
11. Debugging Swift Concurrency
11. Debugging Swift Concurrency
Debugging kode async/await dan actor membutuhkan pendekatan khusus karena eksekusi tidak lagi linear.
Melihat Cooperative Thread Pool
swift
# Lihat semua threads Swift Concurrency
(lldb) bt all
# Cari thread dengan nama seperti:
# "com.apple.root.default-qos.cooperative"
# "swift_task_switch" di call stack
# Thread Swift Concurrency menggunakan cooperative scheduling
# Satu OS thread bisa menjalankan banyak Swift Tasks secara bergantian
Async Stack Trace
Xcode 14+ mendukung async backtrace — menampilkan "logical" call stack melintasi await boundaries, bukan hanya OS-level stack.
swift
# Di Xcode Debug Navigator: pilih thread dengan ikon async (zigzag)
# LLDB command untuk async backtrace:
(lldb) thread backtrace
# Output akan terlihat seperti:
# frame #0: ... dalam fungsi async saat ini
# frame #1: await continuation → fungsi yang memanggil dengan await
# frame #2: ... dst (async call chain)
Breakpoint di Task Boundaries
swift
# Berhenti saat Task dibuat
(lldb) breakpoint set --name "swift_task_create"
# Berhenti saat continuation di-resume
(lldb) breakpoint set --name "swift_continuation_resume"
# Berhenti saat actor switch terjadi
(lldb) breakpoint set --name "swift_task_switch"
Mendeteksi Data Race
Aktifkan Thread Sanitizer (TSan) di build settings untuk mendeteksi data race otomatis:
swift
# Di Xcode: Edit Scheme → Run → Diagnostics → Thread Sanitizer ✓
# Atau dari command line:
# xcodebuild -scheme MyApp -enableThreadSanitizer YES
# TSan akan pause di LLDB saat race terdeteksi dengan pesan:
# WARNING: ThreadSanitizer: Swift access race
# Read of size 8 at 0x... by thread T2
# Previous write of size 8 at 0x... by thread T1
Debugging Actor Isolation
swift
# Ketika ada warning/error actor isolation, debug dengan:
(lldb) bt
# Perhatikan frame yang berisi "swift_task_switch" atau "swift_job_run"
# Cek apakah eksekusi di main thread
(lldb) expr Thread.isMainThread
(lldb) expr DispatchQueue.currentLabel
# Xcode 16 menampilkan actor context di thread list:
# thread #1 [main, @MainActor] MyApp`...
Debugging Deadlock di Actor
swift
# Saat app freeze (kemungkinan deadlock):
# Pause di Xcode (Debug → Pause) atau Ctrl+C di terminal LLDB
# Lihat semua threads untuk menemukan yang waiting
(lldb) bt all
# Cari pattern:
# Thread A: menunggu di swift_task_switch menuju actor X
# Thread B (actor X): menunggu di swift_task_switch menuju actor Y
# Thread C (actor Y): menunggu sesuatu yang di-hold Thread A
# → Circular deadlock
# Inspect task queue
(lldb) expr Swift.withUnsafeCurrentTask { task in task?.isCancelled }