Fix PyDict REPL completion without GIL by Beforerr · Pull Request #772 · JuliaPy/PythonCall.jl · GitHub
Skip to content

Fix PyDict REPL completion without GIL#772

Open
Beforerr wants to merge 1 commit into
JuliaPy:mainfrom
Beforerr:fix/pydict-repl-completion-gil
Open

Fix PyDict REPL completion without GIL#772
Beforerr wants to merge 1 commit into
JuliaPy:mainfrom
Beforerr:fix/pydict-repl-completion-gil

Conversation

@Beforerr

@Beforerr Beforerr commented May 18, 2026

Copy link
Copy Markdown

Summary

In normal REPL operation, the main Python thread can still hold the GIL while Julia runs completion on an interactive/default thread. Dict-key completion then evaluates a PyDict from that completion thread, which is not safe to call Python directly.

This routes the Python-touching pieces through the existing main-thread machinery when needed:

  • keys(::PyDict) iteration used by REPL.REPLCompletions.find_dict_matches
  • two-arg show(::Py), because completion calls repr(key) and default PyDict keys are Py

If the current task already owns the GIL, the call stays direct. Otherwise it dispatches to C.on_main_thread.

MWE

This reproduces the crash on main here with julia --project -t 2, reaching PyObject_GetIter from iterate(::KeySet{<:PyDict}) inside REPLCompletions.find_dict_matches.

using PythonCall, REPL

d = PyDict(Dict("foo" => 1, "bar" => 2))
t = Threads.@spawn REPL.REPLCompletions.completions("d[", 2, @__MODULE__)
wait(t)
fetch(t)

@Beforerr Beforerr force-pushed the fix/pydict-repl-completion-gil branch 2 times, most recently from 748d38c to 5e41917 Compare May 18, 2026 15:54
@cjdoris

cjdoris commented May 18, 2026

Copy link
Copy Markdown
Member

@Beforerr Beforerr force-pushed the fix/pydict-repl-completion-gil branch from 5e41917 to 9b0f572 Compare May 18, 2026 18:01
@Beforerr

Beforerr commented May 18, 2026

Copy link
Copy Markdown
Author

Thanks, you were right. The original MWE was testing the wrong shape and GIL.@lock could deadlock when completion runs off the Python thread while the main thread owns the GIL.

I rewrote this to use the existing main-thread path instead. The only wrapped paths now are PyDict key iteration for find_dict_matches and show(::Py) for the repr(key) call.

Checked with focused tests and a -t 2 spawned completion case.

@Beforerr Beforerr force-pushed the fix/pydict-repl-completion-gil branch from 9b0f572 to 2e0bea9 Compare May 18, 2026 18:09
@Beforerr

Beforerr commented May 18, 2026

Copy link
Copy Markdown
Author

@Beforerr Beforerr force-pushed the fix/pydict-repl-completion-gil branch from 2e0bea9 to 3a17ba7 Compare May 18, 2026 18:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants