Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ctrl-C broken – repeating Ctrl-C required on Julia 1.8 #46635

Closed
fonsp opened this issue Sep 5, 2022 · 12 comments · Fixed by #47901
Closed

Ctrl-C broken – repeating Ctrl-C required on Julia 1.8 #46635

fonsp opened this issue Sep 5, 2022 · 12 comments · Fixed by #47901
Assignees
Labels
io Involving the I/O subsystem: libuv, read, write, etc. regression Regression in behavior compared to a previous version
Milestone

Comments

@fonsp
Copy link
Member

fonsp commented Sep 5, 2022

Since Julia 1.8, a single Ctrl-C does not work. I always need to repeat Ctrl-C multiple times to get the forced SIGINT (with WARNING: Force throwing a SIGINT):

Schermopname.2022-09-05.om.12.21.45.mov

I found this to be the case for anything that I interrupt, not just sleep. This means that, to exit Pluto, Jupyter, a web server or any other long running process, users will now need to hold down Ctrl-C, printing multiple WARNINGs, which makes Julia look unstable.

Julia Version 1.8.0
Commit 5544a0fab76 (2022-08-17 13:38 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin21.4.0)
  CPU: 8 × Apple M1
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-13.0.1 (ORCJIT, westmere)
  Threads: 1 on 8 virtual cores
Julia Version 1.7.0
Commit 3bf9d17731 (2021-11-30 12:12 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin19.5.0)
  CPU: Apple M1
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-12.0.1 (ORCJIT, westmere)

Same problem with the MacOS ARM build.

@pankgeorg
Copy link

pankgeorg commented Sep 5, 2022

I can confirm I have the same issue on Windows 11 on an Intel processor and Windows Terminal 1.15.2203.0

Windows 11 Pro Insider Preview Build 25193.rs_prelease.220829-1428 (no legacy cmd, unfortunately!)

image
image

julia> versioninfo()
Julia Version 1.8.0
Commit 5544a0fab7 (2022-08-17 13:38 UTC)
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: 8 × 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-13.0.1 (ORCJIT, tigerlake)
  Threads: 1 on 8 virtual cores

@benz0li
Copy link
Contributor

benz0li commented Sep 5, 2022

Debian 11 (bullseye), amd64, JupyterLab Terminal:

julia> versioninfo()
Julia Version 1.8.0
Commit 5544a0fab76 (2022-08-17 13:38 UTC)
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 40 × Intel(R) Xeon(R) Silver 4210R CPU @ 2.40GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-13.0.1 (ORCJIT, cascadelake)
  Threads: 1 on 40 virtual cores
Environment:
  JULIA_VERSION = 1.8.0
  JULIA_PATH = /opt/julia

julia> sleep(123)
^C^C^C^C^C^C^C^C^CWARNING: Force throwing a SIGINT
ERROR: InterruptException:
Stacktrace:
 [1] poptask(W::Base.InvasiveLinkedListSynchronized{Task})
   @ Base ./task.jl:921
 [2] wait()
   @ Base ./task.jl:930
 [3] wait(c::Base.GenericCondition{Base.Threads.SpinLock})
   @ Base ./condition.jl:124
 [4] _trywait(t::Timer)
   @ Base ./asyncevent.jl:138
 [5] wait
   @ ./asyncevent.jl:155 [inlined]
 [6] sleep(sec::Int64)
   @ Base ./asyncevent.jl:240
 [7] top-level scope
   @ REPL[2]:1

julia> 

Debian 11 (bullseye), arm64, JupyterLab Terminal:

julia> versioninfo()
Julia Version 1.8.0
Commit 5544a0fab76 (2022-08-17 13:38 UTC)
Platform Info:
  OS: Linux (aarch64-linux-gnu)
  CPU: 8 × unknown
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-13.0.1 (ORCJIT, generic)
  Threads: 1 on 8 virtual cores
Environment:
  JULIA_VERSION = 1.8.0
  JULIA_PATH = /opt/julia

julia> sleep(123)
^C^C^C^C^C^C^C^C^CWARNING: Force throwing a SIGINT
ERROR: InterruptException:
Stacktrace:
 [1] poptask(W::Base.InvasiveLinkedListSynchronized{Task})
   @ Base ./task.jl:921
 [2] wait()
   @ Base ./task.jl:930
 [3] wait(c::Base.GenericCondition{Base.Threads.SpinLock})
   @ Base ./condition.jl:124
 [4] _trywait(t::Timer)
   @ Base ./asyncevent.jl:138
 [5] wait
   @ ./asyncevent.jl:155 [inlined]
 [6] sleep(sec::Int64)
   @ Base ./asyncevent.jl:240
 [7] top-level scope
   @ REPL[2]:1

julia> 

ℹ️ May be reproduced at https://demo.jupyter.b-data.ch or with docker run --rm -it -p 8888:8888 registry.gitlab.b-data.ch/jupyterlab/julia/pubtools

@gbaraldi
Copy link
Member

gbaraldi commented Sep 5, 2022

A bisect shows that the first bad commit is 0eaf35a .
@vtjnash

@JeffBezanson JeffBezanson added the regression Regression in behavior compared to a previous version label Sep 7, 2022
@fonsp
Copy link
Member Author

fonsp commented Sep 20, 2022

It looks like it is still possible to interrupt Pkg precompilation with a single Ctrl+C (video), strange...

@JeffBezanson JeffBezanson added the io Involving the I/O subsystem: libuv, read, write, etc. label Sep 20, 2022
@JeffBezanson JeffBezanson added this to the 1.9 milestone Sep 20, 2022
@fonsp
Copy link
Member Author

fonsp commented Sep 20, 2022

Narrowing down on the interrupt in Pkg precompilation, I found that Ctrl+C still works reliably in this snippet:

while true
	sleep(.1)
end
Details
julia> sleep(100)
^C^C^C^C^C^C^CWARNING: Force throwing a SIGINT
ERROR: InterruptException:

julia> while true
       sleep(100)
       end
^C^C^C^C^C^C^C^CWARNING: Force throwing a SIGINT
ERROR: InterruptException:

julia> while true
       sleep(.1)
       end
^CERROR: InterruptException:
Stacktrace:
 [1] poptask(W::Base.InvasiveLinkedListSynchronized{Task})
   @ Base ./task.jl:921
 [2] wait()
   @ Base ./task.jl:930
 [3] wait(c::Base.GenericCondition{Base.Threads.SpinLock})
   @ Base ./condition.jl:124
 [4] _trywait(t::Timer)
   @ Base ./asyncevent.jl:138
 [5] wait
   @ ./asyncevent.jl:155 [inlined]
 [6] sleep(sec::Float64)
   @ Base ./asyncevent.jl:240
 [7] top-level scope
   @ ./REPL[14]:2

julia> 

This means that Packages that use the "Press Ctrl+C to stop" UI, like an HTTP.jl server, can use this as a workaround.

Example with HTTP.jl:

Instead of:

server = HTTP.serve!(...)

@info "Server running, press Ctrl+C to interrupt..."
wait(server)

You can use:

server = HTTP.serve!(...)

@info "Server running, press Ctrl+C to interrupt..."
try
	while Base.isopen(server)
		sleep(.1)
	end
catch e
	@info "Closing server..."
	close(server)
	wait(server)
end

@vtjnash
Copy link
Member

vtjnash commented Sep 20, 2022

The more correct way to read ^C in a UI is exemplified here in runtests.jl:

julia/test/runtests.jl

Lines 221 to 232 in 276af84

# Monitor stdin and kill this task on ^C
# but don't do this on Windows, because it may deadlock in the kernel
running_tests = Dict{String, DateTime}()
if !Sys.iswindows() && isa(stdin, Base.TTY)
t = current_task()
stdin_monitor = @async begin
term = REPL.Terminals.TTYTerminal("xterm", stdin, stdout, stderr)
try
REPL.Terminals.raw!(term, true)
while true
c = read(term, Char)
if c == '\x3'

@quinnj
Copy link
Member

quinnj commented Oct 8, 2022

I don't think it's reasonable to expect HTTP.jl internals to be messing with REPL/Terminals/raw character input. I also don't really understand what changed though and why doing Ctrl + C doesn't throw an InteruptException like it used to? Maybe we just need to provide an interuptible_wait() function in Base that people can call if they want a way to reliably allow and catch an InteruptException?

@clarkevans
Copy link
Member

@vtnash Besides documenting this use case as a solution to CTRL+C, could HTTP.jl have a function that implements the solution so that applications could use a standard tested piece of code that can be improved over time?

@mind6
Copy link

mind6 commented Nov 5, 2022

does a test framework exist for testing keystroke interrupts?

@AbhimanyuAryan
Copy link

yes same issue MacOS and Windows

@toollu
Copy link

toollu commented Nov 15, 2022

I don't understand why this is not patched in 1.8.x but put back for 1.9 which is probably months from a release

@PallHaraldsson
Copy link
Contributor

PallHaraldsson commented Nov 15, 2022

Julia 1.9 seems actually close, but I believe there's no solution [PR] yet (though a workaround in Pluto), so I'm afraid it will not make it into 1.9, maybe 1.10, which IS months away. Though if solved likely could be backported to 1.9. I'm guessing the solution isn't too easy (and the behavior that worked, was never promised, so some tradeoff with keeping it, not simply a bug).

It's certainly annoying and what I do instead (kills the process on Linux, so not the best workaround for REPL work):
CTRL-Z
kill %1

@fonsp fonsp changed the title Repeating Ctrl-C required on Julia 1.8 Ctrl-C broken – repeating Ctrl-C required on Julia 1.8 Nov 29, 2022
JeffBezanson added a commit that referenced this issue Dec 14, 2022
fixes #46635

Co-authored-by: Jameson Nash <vtjnash@gmail.com>
vtjnash added a commit that referenced this issue Dec 16, 2022
fixes #46635

co-authored-by: Jameson Nash <vtjnash@gmail.com>
KristofferC pushed a commit that referenced this issue Dec 16, 2022
fixes #46635

co-authored-by: Jameson Nash <vtjnash@gmail.com>
(cherry picked from commit b6f32bc)
KristofferC pushed a commit that referenced this issue Dec 16, 2022
fixes #46635

co-authored-by: Jameson Nash <vtjnash@gmail.com>
(cherry picked from commit b6f32bc)
KristofferC added a commit that referenced this issue Dec 16, 2022
fixes #46635

co-authored-by: Jameson Nash <vtjnash@gmail.com>
(cherry picked from commit b6f32bc)

Co-authored-by: Jeff Bezanson <jeff.bezanson@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
io Involving the I/O subsystem: libuv, read, write, etc. regression Regression in behavior compared to a previous version
Projects
None yet
Development

Successfully merging a pull request may close this issue.