Skip to content

Commit 86ff93b

Browse files
REPL: spawn to avoid blocking typing, fix pkg repl transition sequencing (#54785)
Based on #54760 (comment) This changes the `prompt!` design to not consume on the two tasks until inside the lock and spawns the two tasks to avoid blocking typing
1 parent d3b8ebf commit 86ff93b

File tree

1 file changed

+18
-10
lines changed

1 file changed

+18
-10
lines changed

stdlib/REPL/src/LineEdit.jl

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2824,22 +2824,27 @@ keymap_data(ms::MIState, m::ModalInterface) = keymap_data(state(ms), mode(ms))
28242824

28252825
function prompt!(term::TextTerminal, prompt::ModalInterface, s::MIState = init_state(term, prompt))
28262826
Base.reseteof(term)
2827+
l = Base.ReentrantLock()
2828+
t1 = Threads.@spawn :interactive while true
2829+
wait(s.async_channel)
2830+
status = @lock l begin
2831+
fcn = take!(s.async_channel)
2832+
fcn(s)
2833+
end
2834+
status (:ok, :ignore) || break
2835+
end
28272836
raw!(term, true)
28282837
enable_bracketed_paste(term)
28292838
try
28302839
activate(prompt, s, term, term)
28312840
old_state = mode(s)
2832-
l = Base.ReentrantLock()
2833-
t = @async while true
2834-
fcn = take!(s.async_channel)
2835-
status = @lock l fcn(s)
2836-
status (:ok, :ignore) || break
2837-
end
2838-
Base.errormonitor(t)
2839-
while true
2840-
kmap = keymap(s, prompt)
2841-
fcn = match_input(kmap, s)
2841+
# spawn this because the main repl task is sticky (due to use of @async and _wait2)
2842+
# and we want to not block typing when the repl task thread is busy
2843+
t2 = Threads.@spawn :interactive while true
2844+
eof(term) || peek(term, Char) # wait before locking but don't consume
28422845
@lock l begin
2846+
kmap = keymap(s, prompt)
2847+
fcn = match_input(kmap, s)
28432848
kdata = keymap_data(s, prompt)
28442849
s.current_action = :unknown # if the to-be-run action doesn't update this field,
28452850
# :unknown will be recorded in the last_action field
@@ -2870,7 +2875,10 @@ function prompt!(term::TextTerminal, prompt::ModalInterface, s::MIState = init_s
28702875
end
28712876
end
28722877
end
2878+
return fetch(t2)
28732879
finally
2880+
put!(s.async_channel, Returns(:done))
2881+
wait(t1)
28742882
raw!(term, false) && disable_bracketed_paste(term)
28752883
end
28762884
# unreachable

0 commit comments

Comments
 (0)