Commit 7d7bf7e
Dani Pinyol
fix: rare crash due to memoty race condition
The vectors PYJLVALUES and PYJLFREEVALUES are modified without any protection against GC-triggered re-entrancy.
_pyjl_dealloc(o1) or PyJuliaValue_SetValue
└→ push!(PYJLFREEVALUES, idx) # begins resize (sets internal flag)
└→ vector must grow → allocates → triggers Julia GC
└→ GC collects a Py object → runs py_finalizer
└→ enqueue(ptr) → PyGILState_Check()==1 (same thread holds GIL)
└→ Py_DecRef(ptr) → refcount hits 0
└→ _pyjl_dealloc(o2)
└→ push!(PYJLFREEVALUES, idx2) ← BOOM: flag already set
ConcurrencyViolationError!
1. push! needs to grow the vector (exceeds capacity), so it allocates
2. The allocation triggers Julia GC, which runs finalizers
3. A finalizer calls Py_DecRef (because enqueue sees the GIL is held on this same thread), dropping refcount to 0, which triggers _pyjl_dealloc re-entrantly on the same vector
This is especially likely during shutdown (at_jl_exit → jl_atexit_hook), because jl_gc_run_all_finalizers runs finalizers on the calling thread (the main thread, which holds the GIL).
Many Py objects are finalized at once, repeatedly pushing to PYJLFREEVALUES, and each push that triggers a reallocation can cause the re-entrant chain.
Disabled Julia's GC during the critical vector modifications, so that push!/pop! cannot trigger allocation-based GC,
which prevents the finalizer chain from re-entering.
Added a SpinLock as defense-in-depth against true multi-thread races.1 parent 8f7baa5 commit 7d7bf7e
1 file changed
+16
-0
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
| 28 | + | |
| 29 | + | |
28 | 30 | | |
29 | 31 | | |
30 | 32 | | |
| |||
39 | 41 | | |
40 | 42 | | |
41 | 43 | | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
42 | 50 | | |
43 | 51 | | |
| 52 | + | |
| 53 | + | |
44 | 54 | | |
45 | 55 | | |
46 | 56 | | |
| |||
375 | 385 | | |
376 | 386 | | |
377 | 387 | | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
378 | 392 | | |
379 | 393 | | |
380 | 394 | | |
381 | 395 | | |
382 | 396 | | |
383 | 397 | | |
384 | 398 | | |
| 399 | + | |
| 400 | + | |
385 | 401 | | |
386 | 402 | | |
387 | 403 | | |
| |||
0 commit comments