Skip to content

Crashes with Julia 1.12 and Revise.jl #1095

Closed

Description

@fabmazz

I have been using PyPlot (with PyCall) with Revise.jl quite well in the past years, but after the upgrade to Julia 1.12 I see now constant crashes. I've tried to debug these, but they happen quite randomly. I was about to point the issue as happening only in IJulia kernels, when I started seeing them in Julia REPL as well.

These crashes can happen whenever, and are not related to calling "plot" functions.

I have tried reinstalling PyCall and PyPlot with ENV["PYTHON"] = "" (today) and verified the installation happens with a clean Conda.jl environment.

Here is an example of simple commands that trigger the crash:

$ julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.12.3 (2025-12-15)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org release
|__/                   |

julia> using Base.Threads

julia> threadpool()
:interactive

julia> nthreads()
1

julia> Threads.nthreads(:default)
1

julia> using Revise

julia> using PyPlot

[857707] signal 11 (1): Segmentation fault
in expression starting at REPL[6]:1
_PyInterpreterState_GET at /usr/local/src/conda/python-3.12.12/Include/internal/pycore_pystate.h:133 [inlined]
notify_code_watchers at /usr/local/src/conda/python-3.12.12/Objects/codeobject.c:32
code_dealloc at /usr/local/src/conda/python-3.12.12/Objects/codeobject.c:1705
pydecref_ at /home/mazza/.julia/packages/PyCall/1gn3u/src/PyCall.jl:118 [inlined]
pydecref at /home/mazza/.julia/packages/PyCall/1gn3u/src/PyCall.jl:123
jfptr_pydecref_8808 at /home/mazza/.julia/compiled/v1.12/PyCall/GkzkC_o0cEr.so (unknown line)
run_finalizer at /cache/build/tester-amdci4-9/julialang/julia-release-1-dot-12/src/gc-common.c:180
jl_gc_run_finalizers_in_list at /cache/build/tester-amdci4-9/julialang/julia-release-1-dot-12/src/gc-common.c:270
run_finalizers at /cache/build/tester-amdci4-9/julialang/julia-release-1-dot-12/src/gc-common.c:316
ijl_gc_collect at /cache/build/tester-amdci4-9/julialang/julia-release-1-dot-12/src/gc-stock.c:3483
maybe_collect at /cache/build/tester-amdci4-9/julialang/julia-release-1-dot-12/src/gc-stock.c:349 [inlined]
ijl_gc_managed_malloc at /cache/build/tester-amdci4-9/julialang/julia-release-1-dot-12/src/gc-stock.c:3811
jl_alloc_genericmemory_unchecked at /cache/build/tester-amdci4-9/julialang/julia-release-1-dot-12/src/genericmemory.c:38
_new_genericmemory_ at /cache/build/tester-amdci4-9/julialang/julia-release-1-dot-12/src/genericmemory.c:68 [inlined]
jl_alloc_genericmemory at /cache/build/tester-amdci4-9/julialang/julia-release-1-dot-12/src/genericmemory.c:101
ijl_array_grow_end at /cache/build/tester-amdci4-9/julialang/julia-release-1-dot-12/src/array.c:222
_append_symbol_to_bindings_array at /cache/build/tester-amdci4-9/julialang/julia-release-1-dot-12/src/module.c:1958 [inlined]
append_module_names at /cache/build/tester-amdci4-9/julialang/julia-release-1-dot-12/src/module.c:1980
ijl_module_names at /cache/build/tester-amdci4-9/julialang/julia-release-1-dot-12/src/module.c:2001
#unsorted_names#4 at ./runtime_internals.jl:119 [inlined]
unsorted_names at ./runtime_internals.jl:119 [inlined]
#names#3 at ./runtime_internals.jl:118 [inlined]
names at ./runtime_internals.jl:118 [inlined]
_subtypes_in! at /cache/build/tester-amdci4-9/julialang/julia-release-1-dot-12/usr/share/julia/stdlib/v1.12/InteractiveUtils/src/InteractiveUtils.jl:266
subtypes at /cache/build/tester-amdci4-9/julialang/julia-release-1-dot-12/usr/share/julia/stdlib/v1.12/InteractiveUtils/src/InteractiveUtils.jl:303 [inlined]
_foreach_subtype! at /home/mazza/.julia/packages/Revise/icvyF/src/visit.jl:43
_foreach_subtype! at /home/mazza/.julia/packages/Revise/icvyF/src/visit.jl:49
_foreach_subtype! at /home/mazza/.julia/packages/Revise/icvyF/src/visit.jl:49
foreach_subtype at /home/mazza/.julia/packages/Revise/icvyF/src/visit.jl:38 [inlined]
#__init__##2 at /home/mazza/.julia/packages/Revise/icvyF/src/packagedef.jl:1658
unknown function (ip: 0x7f711c6a894f) at (unknown file)
jl_apply at /cache/build/tester-amdci4-9/julialang/julia-release-1-dot-12/src/julia.h:2391 [inlined]
start_task at /cache/build/tester-amdci4-9/julialang/julia-release-1-dot-12/src/task.c:1249
Allocations: 5202189 (Pool: 5202112; Big: 77); GC: 7
Segmentation fault (core dumped)

Activity

  1. yuyichao commented on Jan 7, 2026

    @yuyichao
    Collaborator

    I’ve seen these happen without revise when the finalizer runs on a thread that python isnt aware of.

  2. axsk commented on Jan 13, 2026

    @axsk

    Just coming back to Julia after a christmas break, updated to 1.12.4, and was immediately greeted with exactly this as well :(
    Just for reference, as this might be related: #1090

    Only workaround that works so far for me: julia --threads=1...

  3. axsk commented on Jan 13, 2026

    @axsk

    I also seemingly randombly obtained this variation of this error

    Error
    Fatal Python error: PyThreadState_Get: the function must be called with the GIL held, after Python initialization and before Python finalization, but the GIL is released (the current Python thread state is NULL)                                      |  ETA: 0:03:22        
    Python runtime state: initialized1 ns                                                                                                                                                                                                                                           
                speed: 5.5616218347885614e-5 ns/s                                                                                                                                                                                                                                   
    Thread 0x00007f0e1d6bb100 (most recent call first):                                                                                                                                                                                                                             
      File "/data/numerik/people/bzfsikor/conda/envs/conda_jl/lib/python3.13/site-packages/openmm/openmm.py", line 10995 in step                                                                                                                                                    
      File "/data/numerik/people/bzfsikor/conda/envs/conda_jl/lib/python3.13/site-packages/openmm/app/simulation.py", line 229 in _simulate                                                                                                                                         
      File "/data/numerik/people/bzfsikor/conda/envs/conda_jl/lib/python3.13/site-packages/openmm/app/simulation.py", line 150 in step                                                                                                                                              
                                                                                                                                                                                                                                                                                    
    [29084] signal 6 (-6): Aborted
    in expression starting at REPL[2]:1
    unknown function (ip: 0x7f0e1d769eec) at /lib/x86_64-linux-gnu/libc.so.6
    gsignal at /lib/x86_64-linux-gnu/libc.so.6 (unknown line)
    abort at /lib/x86_64-linux-gnu/libc.so.6 (unknown line)
    fatal_error_exit at /usr/local/src/conda/python-3.13.5/Python/pylifecycle.c:3256 [inlined]                                                                                                                                                               |  ETA: 0:03:22
    fatal_error at /usr/local/src/conda/python-3.13.5/Python/pylifecycle.c:3402
    _Py_FatalErrorFunc at /usr/local/src/conda/python-3.13.5/Python/pylifecycle.c:3488
    _Py_EnsureFuncTstateNotNULL at /usr/local/src/conda/python-3.13.5/Include/internal/pycore_pystate.h:189 [inlined]
    PyThreadState_Get at /usr/local/src/conda/python-3.13.5/Python/pystate.c:2427 [inlined]
  4. fabmazz commented on Jan 13, 2026

    @fabmazz
    Author
  5. a2ray commented on Feb 9, 2026

    @a2ray

    I too thought this was Revise related, but no, it was the reandomness that fooled me into thinking so. Same error as the OP

    [581087] signal 11 (1): Segmentation fault
    in expression starting at REPL[23]:1
    _PyInterpreterState_GET at /usr/local/src/conda/python-3.12.12/Include/internal/pycore_pystate.h:133 [inlined]
    _PyType_Lookup at /usr/local/src/conda/python-3.12.12/Objects/typeobject.c:4729 [inlined]
    _PyObject_LookupSpecial at /usr/local/src/conda/python-3.12.12/Objects/typeobject.c:2167
    _dir_object at /usr/local/src/conda/python-3.12.12/Objects/object.c:1758 [inlined]
    PyObject_Dir at /usr/local/src/conda/python-3.12.12/Objects/object.c:1790
    

    and starting with 1,0 for threads seems to solve it for now on julia-1.12.4.

    This is only happening on the Linux cluster though, not on my Mac M2 -- perhaps threading is handled differently there?

  6. kafisatz commented on May 12, 2026

    @kafisatz

    I run into julia crashes very often.
    Many of my packages use PyCall.
    I find it very difficult to tell whether the crash is Revise or PyCall related (or both).
    Also, I don't know yet where to retrieve the logs in VS code when Julia crashes (I am sure it is somewhere). Thus I often us a plain terminal (pwsh, wt) trying to reproduce the crash.

    But it turns out that the crashes are not alyways reproducible.

    I am mainly commenting here to 'subscribe' to this issue.
    Below is a log from today. Unfortunately I cannot share the full code (as it is used for client work).

    Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
    Exception: EXCEPTION_ACCESS_VIOLATION at 0x7ffa030d918c -- PyInstanceMethod_Function at C:\Users\bernhard.koenig\.julia\conda\3\x86_64\python312.dll (unknown line)
    in expression starting at REPL[7]:1
    PyInstanceMethod_Function at C:\Users\bernhard.koenig\.julia\conda\3\x86_64\python312.dll (unknown line)
    PyCode_GetCode at C:\Users\bernhard.koenig\.julia\conda\3\x86_64\python312.dll (unknown line)
    pydecref_ at C:\Users\bernhard.koenig\.julia\packages\PyCall\1gn3u\src\PyCall.jl:118 [inlined]
    pydecref at C:\Users\bernhard.koenig\.julia\packages\PyCall\1gn3u\src\PyCall.jl:123
    jfptr_pydecref_9417 at C:\Users\bernhard.koenig\.julia\compiled\v1.12\PyCall\GkzkC_5qI8A.dll (unknown line)
    run_finalizer at C:/workdir/src\gc-common.c:180
    jl_gc_run_finalizers_in_list at C:/workdir/src\gc-common.c:270
    run_finalizers at C:/workdir/src\gc-common.c:316
    jl_mutex_unlock at C:/workdir/src\julia_locks.h:80 [inlined]
    jl_get_module_binding at C:/workdir/src\module.c:1566
    ijl_boundp at C:/workdir/src\module.c:1470
    jl_f_isdefinedglobal at C:/workdir/src\builtins.c:1376
    isvisible at .\show.jl:1023
    show_type_name at .\show.jl:1089
    _show_type at .\show.jl:971
    show at .\show.jl:968
    print at .\strings\io.jl:35
    print_to_string at .\strings\io.jl:151
    string at .\strings\io.jl:193
    jfptr_string_73108.1 at C:\Users\bernhard.koenig\.julia\juliaup\julia-1.12.6+0.x64.w64.mingw32\lib\julia\sys.dll (unknown line)
    iterate at .\generator.jl:48 [inlined]
    _collect at .\array.jl:810
    collect_similar at .\array.jl:732 [inlined]
    map at .\abstractarray.jl:3372 [inlined]
    _subtypes_in! at C:\workdir\usr\share\julia\stdlib\v1.12\InteractiveUtils\src\InteractiveUtils.jl:281
    subtypes at C:\workdir\usr\share\julia\stdlib\v1.12\InteractiveUtils\src\InteractiveUtils.jl:303 [inlined]
    _foreach_subtype! at C:\Users\bernhard.koenig\.julia\packages\Revise\b0dDX\src\visit.jl:43
    _foreach_subtype! at C:\Users\bernhard.koenig\.julia\packages\Revise\b0dDX\src\visit.jl:49
    _foreach_subtype! at C:\Users\bernhard.koenig\.julia\packages\Revise\b0dDX\src\visit.jl:49
    foreach_subtype at C:\Users\bernhard.koenig\.julia\packages\Revise\b0dDX\src\visit.jl:38 [inlined]
    #__init__##2 at C:\Users\bernhard.koenig\.julia\packages\Revise\b0dDX\src\packagedef.jl:1661
    unknown function (ip: 00000213fce724a4) at (unknown file)
    jl_apply at C:/workdir/src\julia.h:2391 [inlined]
    start_task at C:/workdir/src\task.c:1252
    Allocations: 51106352 (Pool: 51103756; Big: 2596); GC: 25
    
    Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
    Exception: EXCEPTION_ACCESS_VIOLATION at 0x7ffa03263854 -- Py_FinalizeEx at C:\Users\bernhard.koenig\.julia\conda\3\x86_64\python312.dll (unknown line)
    in expression starting at REPL[7]:1
    Py_FinalizeEx at C:\Users\bernhard.koenig\.julia\conda\3\x86_64\python312.dll (unknown line)
    Py_Finalize at C:\Users\bernhard.koenig\.julia\packages\PyCall\1gn3u\src\pyinit.jl:125
    jfptr_Py_Finalize_11937 at C:\Users\bernhard.koenig\.julia\compiled\v1.12\PyCall\GkzkC_5qI8A.dll (unknown line)
    _atexit at .\initdefs.jl:464
    unknown function (ip: 0000021409dbe74d) at (unknown file)
    jl_apply at C:/workdir/src\julia.h:2391 [inlined]
    ijl_atexit_hook at C:/workdir/src\init.c:260
    ijl_exit at C:/workdir/src\init.c:196
    jl_exception_handler at C:/workdir/src\signals-win.c:343 [inlined]
    jl_exception_handler at C:/workdir/src\signals-win.c:235
    __julia_personality at C:/workdir/src\win32_ucontext.c:28
    _chkstk at C:\WINDOWS\SYSTEM32\ntdll.dll (unknown line)
    RtlLocateExtendedFeature at C:\WINDOWS\SYSTEM32\ntdll.dll (unknown line)
    KiUserExceptionDispatcher at C:\WINDOWS\SYSTEM32\ntdll.dll (unknown line)
    PyInstanceMethod_Function at C:\Users\bernhard.koenig\.julia\conda\3\x86_64\python312.dll (unknown line)
    PyCode_GetCode at C:\Users\bernhard.koenig\.julia\conda\3\x86_64\python312.dll (unknown line)
    pydecref_ at C:\Users\bernhard.koenig\.julia\packages\PyCall\1gn3u\src\PyCall.jl:118 [inlined]
    pydecref at C:\Users\bernhard.koenig\.julia\packages\PyCall\1gn3u\src\PyCall.jl:123
    jfptr_pydecref_9417 at C:\Users\bernhard.koenig\.julia\compiled\v1.12\PyCall\GkzkC_5qI8A.dll (unknown line)
    run_finalizer at C:/workdir/src\gc-common.c:180
    jl_gc_run_finalizers_in_list at C:/workdir/src\gc-common.c:270
    run_finalizers at C:/workdir/src\gc-common.c:316
    jl_mutex_unlock at C:/workdir/src\julia_locks.h:80 [inlined]
    jl_get_module_binding at C:/workdir/src\module.c:1566
    ijl_boundp at C:/workdir/src\module.c:1470
    jl_f_isdefinedglobal at C:/workdir/src\builtins.c:1376
    isvisible at .\show.jl:1023
    show_type_name at .\show.jl:1089
    _show_type at .\show.jl:971
    show at .\show.jl:968
    print at .\strings\io.jl:35
    print_to_string at .\strings\io.jl:151
    string at .\strings\io.jl:193
    jfptr_string_73108.1 at C:\Users\bernhard.koenig\.julia\juliaup\julia-1.12.6+0.x64.w64.mingw32\lib\julia\sys.dll (unknown line)
    iterate at .\generator.jl:48 [inlined]
    _collect at .\array.jl:810
    collect_similar at .\array.jl:732 [inlined]
    map at .\abstractarray.jl:3372 [inlined]
    _subtypes_in! at C:\workdir\usr\share\julia\stdlib\v1.12\InteractiveUtils\src\InteractiveUtils.jl:281
    subtypes at C:\workdir\usr\share\julia\stdlib\v1.12\InteractiveUtils\src\InteractiveUtils.jl:303 [inlined]
    _foreach_subtype! at C:\Users\bernhard.koenig\.julia\packages\Revise\b0dDX\src\visit.jl:43
    _foreach_subtype! at C:\Users\bernhard.koenig\.julia\packages\Revise\b0dDX\src\visit.jl:49
    _foreach_subtype! at C:\Users\bernhard.koenig\.julia\packages\Revise\b0dDX\src\visit.jl:49
    foreach_subtype at C:\Users\bernhard.koenig\.julia\packages\Revise\b0dDX\src\visit.jl:38 [inlined]
    #__init__##2 at C:\Users\bernhard.koenig\.julia\packages\Revise\b0dDX\src\packagedef.jl:1661
    unknown function (ip: 00000213fce724a4) at (unknown file)
    jl_apply at C:/workdir/src\julia.h:2391 [inlined]
    start_task at C:/workdir/src\task.c:1252
    Allocations: 51106352 (Pool: 51103756; Big: 2596); GC: 25
    PS C:\Users\bernhard.koenig\Documents\Repositories\LLCalculationAgent.jl>
    
  7. a2ray commented on May 12, 2026

    @a2ray
  8. daniel-sali commented on May 21, 2026

    @daniel-sali

    I also ran into this issue with a Julia notebook using Julia 1.12.6 and Python 3.13.3 on Ubuntu Noble:

    Root Cause Analysis

    The crash is caused by pydecref_ being called from Julia's GC finalizer system on a thread that does not hold the Python GIL.

    Trigger mechanism

    Julia runs pending finalizers not only during GC collection, but also when unlocking internal mutexes (specifically jl_typeinf_lock after type inference). This means any Julia thread performing compilation can trigger pydecref_ finalizers — and these threads never acquire the Python GIL.

    Call chain (from GDB core dump analysis)

    jl_type_infer → jl_mutex_unlock(jl_typeinf_lock)
      → run_finalizers → jl_gc_run_finalizers_in_list
        → run_finalizer → PyCall.pydecref_
          → Py_DecRef → meth_dealloc
            → PyThreadState_Get()
              → FATAL: "the GIL is released (the current Python thread state is NULL)"
              → abort()
    

    The _finalized[] guard only protects against calls after Py_Finalize — it does nothing for the multi-threaded case during normal operation.

    Why "Run All" triggers it but manual cell execution doesn't

    When cells are executed rapidly (Run All), Julia's JIT compiler runs type inference on background threads. Those threads accumulate finalizers for PyObjects created during earlier cells. When the type inference lock is released, the pending finalizers fire — on the compiler thread, without the GIL.

    Manual step-by-step execution gives Julia time to run finalizers on the main thread (which holds the GIL via PyCall), so the race never occurs.

    Why GC.enable(false) doesn't help

    Finalizers triggered by _jl_mutex_unlock bypass the GC-enable flag — they are not part of the GC collection cycle.

    Fix

    Use PyGILState_Check() to only call Py_DecRef when the current thread already holds the GIL. If a finalizer runs on a thread without the GIL, skip the decref:

    function pydecref_(o::Union{PyPtr,PyObject})
        if !_finalized[] && ccall(@pysym(:Py_IsInitialized), Cint, ()) != 0
            if ccall(@pysym(:PyGILState_Check), Cint, ()) != 0
                ccall(@pysym(:Py_DecRef), Cvoid, (PyPtr,), o)
            end
        end
        return o
    end

    The same fix should be applied to pydecref(::PyBuffer) in pybuffer.jl.

    Why not PyGILState_Ensure/PyGILState_Release?

    We initially tried wrapping with PyGILState_Ensure/Release, but this causes deadlocks: the finalizer thread blocks waiting for the GIL while the main thread (holding the GIL inside a PyCall ccall) waits for that thread's mutex unlock to complete.

    It also segfaults during process exit because PyGILState_Ensure tries to allocate a new thread state after the interpreter is partially torn down (even when Py_IsInitialized() still returns true).

    Trade-off

    The PyGILState_Check approach leaks Python objects when finalizers run on non-GIL-holding threads. In practice this is a small leak — most finalizers run on the main thread during normal operation. The alternative (crash or deadlock) is far worse.

    A more complete fix would queue deferred decrefs and process them on the main thread, but that requires more invasive changes to PyCall.

    Environment

    • Julia 1.12.6, PyCall 1.96.4, Python 3.13.13, TensorFlow 2.21.0
    • Crash is 100% reproducible under "Run All" with multi-cell notebooks that use PyCall + heavy Python libraries (TensorFlow, numpy, etc.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions