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

throwto does not return in certain conditions #25353

Closed
tanmaykm opened this issue Jan 2, 2018 · 6 comments
Closed

throwto does not return in certain conditions #25353

tanmaykm opened this issue Jan 2, 2018 · 6 comments

Comments

@tanmaykm
Copy link
Member

tanmaykm commented Jan 2, 2018

This is fine on the REPL, method returns after interrupting task:

julia> t = @async begin
           while true
               sleep(5)
           end
           end
Task (runnable) @0x00007f1abbdc8010

julia> @assert !istaskdone(t)

julia> Base.throwto(t, InterruptException())
ERROR: InterruptException:
Stacktrace:
 [1] try_yieldto(::typeof(identity), ::Base.RefValue{Task}) at ./event.jl:208
 [2] yieldto at ./event.jl:194 [inlined]
 [3] yieldto at ./event.jl:193 [inlined]
 [4] throwto(::Task, ::Any) at ./event.jl:218
 [5] top-level scope

julia>

But this never comes out, the target task should have exited though:

julia> t = @async begin
           while true
               try
                   sleep(5)
               catch ex
                   error("task interrupted")
               end
           end
           end
Task (runnable) @0x00007fc07a416cb0

julia> @assert !istaskdone(t)

julia> Base.throwto(t, InterruptException())
ERROR (unhandled task failure): task interrupted
Stacktrace:
 [1] error at ./error.jl:33 [inlined]
 [2] macro expansion at ./REPL[1]:6 [inlined]
 [3] (::getfield(, Symbol("##1#2")))() at ./task.jl:348

... needs to be interrupted or killed

And this too, here the target task would not have exited:

julia> t = @async begin
          while true
              try
                  sleep(5)
              catch ex
                  if isa(ex, InterruptException)
                      println("handled this exception, resuming")
                  else
                      rethrow(ex)
                  end
              end
          end
          end
Task (runnable) @0x00007f0fea006cb0

julia> @assert !istaskdone(t)

julia> Base.throwto(t, InterruptException())
handled this exception, resuming

... needs to be interrupted or killed

When not in REPL, throwto does not return in all the above cases, but the behavior is slightly different. It still needs to be interrupted or killed. There also seems to be a race condition here which causes the Workqueue inconsistency error.

$ cat <<EOF > /tmp/y.jl
> t = @async begin
>     while true
>         sleep(5)
>     end
>     end
> 
> @assert !istaskdone(t)
> 
> Base.throwto(t, InterruptException())
> EOF
$ julia /tmp/y.jl 

WARNING: Workqueue inconsistency detected: popfirst!(Workqueue).state != :queued
ERROR (unhandled task failure): InterruptException:
^C
signal (2): Interrupt
in expression starting at /tmp/y.jl:13
unknown function (ip: 0x7fc08e075498)
uv__epoll_wait at /data/Work/julia/sources/julia/deps/srccache/libuv-d8ab1c6a33e77bf155facb54215dd8798e13825d/src/unix/linux-syscalls.c:321
uv__io_poll at /data/Work/julia/sources/julia/deps/srccache/libuv-d8ab1c6a33e77bf155facb54215dd8798e13825d/src/unix/linux-core.c:267
uv_run at /data/Work/julia/sources/julia/deps/srccache/libuv-d8ab1c6a33e77bf155facb54215dd8798e13825d/src/unix/core.c:354
process_events at ./libuv.jl:82 [inlined]
wait at ./event.jl:258
task_done_hook at ./task.jl:257
jl_call_fptr_internal at /data/Work/julia/sources/julia/src/julia_internal.h:380 [inlined]
jl_call_method_internal at /data/Work/julia/sources/julia/src/julia_internal.h:399 [inlined]
jl_apply_generic at /data/Work/julia/sources/julia/src/gf.c:2082
jl_apply at /data/Work/julia/sources/julia/src/julia.h:1474 [inlined]
finish_task at /data/Work/julia/sources/julia/src/task.c:233
start_task at /data/Work/julia/sources/julia/src/task.c:276
unknown function (ip: 0xffffffffffffffff)
unknown function (ip: 0xffffffffffffffff)
Allocations: 826398 (Pool: 825762; Big: 636); GC: 1
@vtjnash
Copy link
Member

vtjnash commented Jan 2, 2018

throwto never returns (although there's some special logic for handling ^C – aka InterruptException – that attempts to re-enable the REPL when detected)

As for the "race condition", the result of yielding directly to an already scheduled/running Task is undefined. It works fine if you don't schedule it twice:

schedule(@task(begin
                  while true
                      sleep(5)
                  end
                  end), InterruptException(), error=true)

@vtjnash vtjnash closed this as completed Jan 2, 2018
@tanmaykm
Copy link
Member Author

tanmaykm commented Jan 2, 2018

What is the recommended way to interrupt or cancel a running task from another task then?

@tanmaykm
Copy link
Member Author

tanmaykm commented Jan 2, 2018

Would schedule(t, InterruptException(), error=true) be the correct way to interrupt the task?

@vtjnash
Copy link
Member

vtjnash commented Jan 2, 2018

@time let sleep = Timer(5)
         t = @schedule wait(sleep) # schedule a delay for 5 seconds
         Base.sleep(1)
         close(sleep) # cancel the sleep after 1 second
         wait(t)
end

@tanmaykm
Copy link
Member Author

tanmaykm commented Jan 2, 2018

In the actual situation that I have, the code being executed in the task is opaque to me.

@vtjnash
Copy link
Member

vtjnash commented Jan 2, 2018

Then no, you can't interrupt it

Keno added a commit that referenced this issue Apr 18, 2019
Too late for 1.2 for which this was originally marked, but nevertheless,
it's a quick change, so might as well get it in now and have it be available
in 1.3.

Fixes #25353
Keno added a commit that referenced this issue Apr 18, 2019
Too late for 1.2 for which this was originally marked, but nevertheless,
it's a quick change, so might as well get it in now and have it be available
in 1.3.

Fixes #25353
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants