Fix race condition potentially overwriting user configuration#4642
Fix race condition potentially overwriting user configuration#4642PatrickHaecker wants to merge 1 commit intoJuliaLang:masterfrom
Conversation
If the user set, e.g.,
```julia
atreplinit() do repl
# Robust against older julia versions
if hasfield(typeof(repl.options), :auto_insert_closing_bracket)
repl.options.auto_insert_closing_bracket = false
end
end
```
in their `startup.jl` it has no effect in VS Code's REPL due to VS Code's plugin loading `Pkg.jl` which is calling `REPL.setup_interface(repl)` inside an `atreplinit` hook, which bakes keymaps before user options are applied. The proper approach is to let `run_frontend` handle interface creation and defer mode initialization until the interface exists.
Note, that this fix is necessary, but not sufficient to make it work, because the same race condition needs to be fixed at least in [TerminalPager.jl](ronisbr/TerminalPager.jl#83) and in [julia-vscode](julia-vscode/julia-vscode#4063).
I used Claude Opus 4.6 while developing this fix.
| # Do not call `REPL.setup_interface` here — it will be called | ||
| # by `run_frontend`, which respects user options set in other | ||
| # `atreplinit` hooks (e.g. `auto_insert_closing_bracket`). | ||
| @async begin |
There was a problem hiding this comment.
I feel there should be some way to register something to run once the interface is created o something like that, instead of needing a sleep loop like this.
There was a problem hiding this comment.
I fully agree. This PR is in the spirit of "at least make it work correctly" not in the spirit of "this is how the optimum solution should look like".
When I implemented this pattern for TerminalPager.jl, I did some analysis on my average notebook and typically it did not sleep at all during a regular REPL start, so it was more of a "if things are unusual still make them work correctly" thing. I haven't done any timing analysis on the Pkg.jl race condition, but I was reliably able to reproduce the problem when starting the REPL in VS Code, so I'd expect it to sleep at least once on my computer in this use case.
As much as I want to have the registration interface, I guess this would need to come earliest with Julia 1.14 and would need to tickle down until it hits the long term supported Julia release until we can get rid of this sleep loop.
There was a problem hiding this comment.
I don't understand all relevant code well enough to state whether JuliaLang/julia#54890 will fix this, but given that we have a synchronization problem here, a synchronization mechanism where only one user at a time gets access to a lock with the REPL guaranteed to get access initially seems to solve the problem.
However, I suggest to not let the perfect be the enemy of the good. Starting with Julia 1.13, we recommend a way which is broken by the current implementation of Pkg.jl, so the REPL in a regular terminal behaves differently (if PKG is not loaded on startup) than the VS Code terminal which is quite annoying.
We can change the sleep time and/or we can progressively increase the sleep time if you want to be sure that the unnecessary relative wait time is limited, but I think we should implement something close to the current PR in Pkg now and then everyone is invited to improve on it in and for 1.14 onward.
If the user set, e.g.,
in their
startup.jlit has no effect in VS Code's REPL due to VS Code's plugin loadingPkg.jlwhich is callingREPL.setup_interface(repl)inside anatreplinithook, which bakes keymaps before user options are applied. The proper approach is to letrun_frontendhandle interface creation and defer mode initialization until the interface exists.Note, that this fix is necessary, but not sufficient to make it work, because the same race condition needs to be fixed at least in TerminalPager.jl and in julia-vscode.
I used Claude Opus 4.6 while developing this fix.