Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion stdlib/REPL/src/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1183,7 +1183,7 @@ find_hist_file() = get(ENV, "JULIA_HISTORY",
!isempty(DEPOT_PATH) ? joinpath(DEPOT_PATH[1], "logs", "repl_history.jl") :
error("DEPOT_PATH is empty and ENV[\"JULIA_HISTORY\"] not set."))

backend(r::AbstractREPL) = hasproperty(r, :backendref) ? r.backendref : nothing
backend(r::AbstractREPL) = hasproperty(r, :backendref) && isdefined(r, :backendref) ? r.backendref : nothing


function eval_on_backend(ast, backend::REPLBackendRef)
Expand Down
15 changes: 12 additions & 3 deletions stdlib/REPL/src/Terminals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,18 @@ cmove_col(t::UnixTerminal, n) = (write(t.out_stream, '\r'); n > 1 && cmove_right
if Sys.iswindows()
function raw!(t::TTYTerminal,raw::Bool)
if Base.ispty(t.in_stream)
run((raw ? `stty raw -echo onlcr -ocrnl opost` : `stty sane`),
t.in_stream, t.out_stream, t.err_stream)
true
try
run((raw ? `stty raw -echo onlcr -ocrnl opost` : `stty sane`),
t.in_stream, t.out_stream, t.err_stream)
true
catch ex
# Fall back to ccall if stty fails (e.g., in some CI environments)
if ex isa ProcessFailedException
ccall(:jl_tty_set_mode, Int32, (Ptr{Cvoid},Int32), t.in_stream.handle::Ptr{Cvoid}, raw) == 0
else
rethrow()
end
end
else
ccall(:jl_tty_set_mode, Int32, (Ptr{Cvoid},Int32), t.in_stream.handle::Ptr{Cvoid}, raw) == 0
end
Expand Down
74 changes: 74 additions & 0 deletions stdlib/REPL/test/bad_history_startup.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

# Test that interactive mode starts up without error when history file is bad

using Test

const BASE_TEST_PATH = joinpath(Sys.BINDIR, "..", "share", "julia", "test")
isdefined(Main, :FakePTYs) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "FakePTYs.jl"))
import .Main.FakePTYs: with_fake_pty

@testset "Bad history file startup" begin
mktempdir() do tmpdir
# Create a bad history file
hist_file = joinpath(tmpdir, "repl_history.jl")
write(hist_file, "{ invalid json content\nmore bad content\n")

julia_exe = Base.julia_cmd()[1]

# Test interactive Julia startup with bad history file
with_fake_pty() do pts, ptm
# Set up environment with our bad history file
nENV = copy(ENV)
nENV["JULIA_HISTORY"] = hist_file

# Start Julia in interactive mode
p = run(detach(setenv(`$julia_exe --startup-file=no --color=no -q`, nENV)), pts, pts, pts, wait=false)
Base.close_stdio(pts)

# Read output until we get the prompt, which indicates successful startup
output = readuntil(ptm, "julia> ", keep=true)
# println("====== subprocess output ======")
# println(output)
# println("====== end subprocess output ======")

# Test conditions:
# 1. We should see the invalid history file error
has_history_error = occursin("Invalid history file", output) ||
occursin("Invalid character", output)
@test has_history_error

# 2. We should NOT see UndefRefError (the bug being fixed)
has_undef_error = occursin("UndefRefError", output)
@test !has_undef_error

# 3. We should see the "Disabling history file" message if the fix works
has_disable_message = occursin("Disabling history file for this session", output)
@test has_disable_message

# Send exit command to clean shutdown
if isopen(ptm)
write(ptm, "exit()\n")
else
@warn "PTY master is already closed before sending exit command"
end

# Read any remaining output until the process exits
try
read(ptm, String)
catch ex
# Handle platform-specific EOF behavior
if ex isa Base.IOError && ex.code == Base.UV_EIO
# This is expected on some platforms (e.g., Linux)
else
rethrow()
end
end

# Wait for process to finish
wait(p)

@test p.exitcode == 0
end
end
end
3 changes: 3 additions & 0 deletions stdlib/REPL/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ end
module TerminalMenusTest
include("TerminalMenus/runtests.jl")
end
module BadHistoryStartupTest
include("bad_history_startup.jl")
end

# Restore the original environment
for k in keys(ENV)
Expand Down