Skip to content

Commit 8ba3b11

Browse files
authored
Try to remove readavailable sections from REPL precompile (#59179)
The `readavailable` is problematic, because it can read partial error messages. The `readuntil`s should be safe because they properly fence between each prompt. If there is some other reason these readavailables are required, let's find out and replace them with proper readuntils if we can. Fixes #59099 (or tries to at least)
1 parent 6175761 commit 8ba3b11

File tree

1 file changed

+19
-8
lines changed

1 file changed

+19
-8
lines changed

stdlib/REPL/src/precompile.jl

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ function repl_workload()
2424
function check_errors(out)
2525
str = String(out)
2626
if occursin("ERROR:", str) && !any(occursin(e, str) for e in allowed_errors)
27-
@error "Unexpected error (Review REPL precompilation with debug_output on):\n$str"
27+
@error "Unexpected error (Review REPL precompilation with debug_output on):\n$str" exception=(
28+
Base.PrecompilableError(), Base.backtrace())
2829
exit(1)
2930
end
3031
end
@@ -40,6 +41,7 @@ function repl_workload()
4041

4142
# This is notified as soon as the first prompt appears
4243
repl_init_event = Base.Event()
44+
repl_init_done_event = Base.Event()
4345

4446
atreplinit() do repl
4547
# Main is closed so we can't evaluate in it, but atreplinit runs at
@@ -48,6 +50,7 @@ function repl_workload()
4850
t = @async begin
4951
wait(repl_init_event)
5052
REPL.activate(REPL.Precompile; interactive_utils=false)
53+
notify(repl_init_done_event)
5154
end
5255
Base.errormonitor(t)
5356
end
@@ -80,6 +83,9 @@ function repl_workload()
8083
"""
8184

8285
JULIA_PROMPT = "julia> "
86+
# The help text for `reinterpret` has example `julia>` prompts in it,
87+
# so use the longer prompt to avoid desychronization.
88+
ACTIVATED_JULIA_PROMPT = "(REPL.Precompile) julia> "
8389
PKG_PROMPT = "pkg> "
8490
SHELL_PROMPT = "shell> "
8591
HELP_PROMPT = "help?> "
@@ -142,18 +148,24 @@ function repl_workload()
142148
end
143149
schedule(repltask)
144150
# wait for the definitive prompt before start writing to the TTY
145-
check_errors(readuntil(output_copy, JULIA_PROMPT))
151+
check_errors(readuntil(output_copy, JULIA_PROMPT, keep=true))
152+
153+
# Switch to the activated prompt
154+
notify(repl_init_event)
155+
wait(repl_init_done_event)
156+
write(ptm, "\n")
157+
# The prompt prints twice - once for the restatement of the input, once
158+
# to indicate ready for the new prompt.
159+
check_errors(readuntil(output_copy, ACTIVATED_JULIA_PROMPT, keep=true))
160+
check_errors(readuntil(output_copy, ACTIVATED_JULIA_PROMPT, keep=true))
161+
146162
write(debug_output, "\n#### REPL STARTED ####\n")
147-
sleep(0.01)
148-
check_errors(readavailable(output_copy))
149163
# Input our script
150164
precompile_lines = split(repl_script::String, '\n'; keepempty=false)
151165
curr = 0
152166
for l in precompile_lines
153167
sleep(0.01) # try to let a bit of output accumulate before reading again
154168
curr += 1
155-
# consume any other output
156-
bytesavailable(output_copy) > 0 && check_errors(readavailable(output_copy))
157169
# push our input
158170
write(debug_output, "\n#### inputting statement: ####\n$(repr(l))\n####\n")
159171
# If the line ends with a CTRL_C, don't write an extra newline, which would
@@ -166,13 +178,12 @@ function repl_workload()
166178
strbuf = ""
167179
while !eof(output_copy)
168180
strbuf *= String(readavailable(output_copy))
169-
occursin(JULIA_PROMPT, strbuf) && break
181+
occursin(ACTIVATED_JULIA_PROMPT, strbuf) && break
170182
occursin(PKG_PROMPT, strbuf) && break
171183
occursin(SHELL_PROMPT, strbuf) && break
172184
occursin(HELP_PROMPT, strbuf) && break
173185
sleep(0.01) # try to let a bit of output accumulate before reading again
174186
end
175-
notify(repl_init_event)
176187
check_errors(strbuf)
177188
end
178189
write(debug_output, "\n#### COMPLETED - Closing REPL ####\n")

0 commit comments

Comments
 (0)