Commit de2e1d9
committed
docs(sdk): codify FFI panic-safety contract at the napi/PyO3 boundary (#32)
Audit outcome for #32 (FFI panic-unwind safety, napi 2.16 / pyo3 0.23):
the boundary is panic-safe today, but the invariant holds by *convention*,
not structure, so it can silently regress. Documents the contract in each
SDK's module doc where future FFI edits will see it.
Key finding (verified against the cargo cache, not memory): napi 2.x does
NOT wrap sync #[napi] bodies in catch_unwind by default — a panic there
aborts the Node process on Rust >= 1.81, it is not a catchable JS error.
Only #[napi] async fns (-> rejected Promise) and #[napi(catch_unwind)] are
safe; ThreadsafeFunction callbacks, spawned tasks, Drop, and module init
are not. PyO3 0.23 does catch #[pyfunction]/#[pymethods]/module-init bodies
(-> PanicException) but not worker-thread with_gil bridges or spawned tasks.
No code change: independent verification confirmed the only production
panic site in each SDK is the lazy Tokio-runtime .expect(), reached from
caught contexts; the genuinely-uncaught paths (spawned tasks, the Python
with_gil callback bridges, no Drop impls exist) are panic-free by
construction via ? / unwrap_or_else / fail-closed defaults. Converting
get_runtime() to a Result would thread through ~75 call sites to defend an
OS-exhaustion panic that is already caught — not worth it.1 parent 8e709c5 commit de2e1d9
2 files changed
Lines changed: 38 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
16 | 37 | | |
17 | 38 | | |
18 | 39 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
16 | 33 | | |
17 | 34 | | |
18 | 35 | | |
| |||
0 commit comments