From f24d9398a3531d12af03724de641a2c1b5d88777 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 28 May 2025 20:59:14 +0000 Subject: [PATCH] remove workaround for controlling terminal behavior in repl_cmd This was originally added as a workaround for the behavior of sh to try to become the terminal process group leader, but no longer relevant since #25006 removed that flag again: ``` julia> run(detach(`bash -i -c "sleep 0"`)) bash: cannot set terminal process group (-1): Inappropriate ioctl for device bash: no job control in this shell Process(`bash -i -c 'sleep 0'`, ProcessExited(0)) ``` Julia recieves SIGTTOU when a process like "sh -i -c" exits (at least for bash and zsh, but not dash, ksh, or csh), since "sh -i" sometimes takes over the controlling terminal, causing julia to stop once the bash process exits. This can be quite annoying, but julia goes through some pains (in libuv) to ensure it doesn't steal the controlling terminal from the parent, and apparently bash is not so careful about it. However, since PR #25006, julia hasn't needed this workaround for this issue, so we can now follow the intended behavior when the child is in the same session group and steals the controlling terminal from the parent. Even if such behavior seems odd, this seems to be the intended behavior per posix design implementation that it gets SIGTTOU when julia later tries to change mode (from cooked -> raw after printing the prompt): http://curiousthing.org/sigttin-sigttou-deep-dive-linux. ``` $ ./julia -q shell> bash -i -c "sleep 1" [1]+ Stopped ./julia julia> run(`zsh -i -c "sleep 0"`) Process(`zsh -i -c 'sleep 0'`, ProcessExited(0)) julia> [1]+ Stopped ./julia ``` --- base/client.jl | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/base/client.jl b/base/client.jl index 5bf658bead437..ae99654c233a8 100644 --- a/base/client.jl +++ b/base/client.jl @@ -32,9 +32,6 @@ stackframe_lineinfo_color() = repl_color("JULIA_STACKFRAME_LINEINFO_COLOR", :bol stackframe_function_color() = repl_color("JULIA_STACKFRAME_FUNCTION_COLOR", :bold) function repl_cmd(cmd, out) - shell = shell_split(get(ENV, "JULIA_SHELL", get(ENV, "SHELL", "/bin/sh"))) - shell_name = Base.basename(shell[1]) - # Immediately expand all arguments, so that typing e.g. ~/bin/foo works. cmd.exec .= expanduser.(cmd.exec) @@ -64,19 +61,15 @@ function repl_cmd(cmd, out) cd(dir) println(out, pwd()) else - @static if !Sys.iswindows() - if shell_name == "fish" - shell_escape_cmd = "begin; $(shell_escape_posixly(cmd)); and true; end" - else - shell_escape_cmd = "($(shell_escape_posixly(cmd))) && true" - end + if !Sys.iswindows() + shell = shell_split(get(ENV, "JULIA_SHELL", get(ENV, "SHELL", "/bin/sh"))) + shell_escape_cmd = shell_escape_posixly(cmd) cmd = `$shell -c $shell_escape_cmd` end try run(ignorestatus(cmd)) catch - # Windows doesn't shell out right now (complex issue), so Julia tries to run the program itself - # Julia throws an exception if it can't find the program, but the stack trace isn't useful + # Julia throws an exception if it can't find the cmd (which may be the shell itself), but the stack trace isn't useful lasterr = current_exceptions() lasterr = ExceptionStack([(exception = e[1], backtrace = [] ) for e in lasterr]) invokelatest(display_error, lasterr)