From 89ae98f1f6b7c96a45030da58e3375f6f2205ac6 Mon Sep 17 00:00:00 2001 From: tan Date: Thu, 5 Sep 2024 05:24:26 +0530 Subject: [PATCH] fix cancelling upload requests Cancelling an upload (PUT) request using the mechanism introduced in #256 was not effective. The upload task was not interrupted, which still blocked and the call to `request` did not return. With this change, cancelling also closes the `input` stream of the request to unblock the upload task. Also changed the `interrupted` variable to be an `Atomic{Bool}`. Ref discussion [here](https://github.com/JuliaLang/Downloads.jl/pull/256#discussion_r1742148570). --- src/Curl/Easy.jl | 6 +++++- src/Downloads.jl | 8 +++++--- test/runtests.jl | 11 +++++++++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/Curl/Easy.jl b/src/Curl/Easy.jl index cf63f50..726d663 100644 --- a/src/Curl/Easy.jl +++ b/src/Curl/Easy.jl @@ -375,7 +375,11 @@ function upload_data(easy::Easy, input::IO) curl_easy_pause(easy.handle, Curl.CURLPAUSE_CONT) wait(easy.ready) easy.input === nothing && break - easy.ready = Threads.Event() + if hasmethod(reset, (Base.Event,)) + reset(easy.ready) + else + easy.ready = Threads.Event() + end end end diff --git a/src/Downloads.jl b/src/Downloads.jl index 7ad35ab..1fe95fa 100644 --- a/src/Downloads.jl +++ b/src/Downloads.jl @@ -396,7 +396,7 @@ function request( # do the request add_handle(downloader.multi, easy) - interrupted = false + interrupted = Threads.Atomic{Bool}(false) if interrupt !== nothing interrupt_task = @async begin # wait for the interrupt event @@ -405,7 +405,9 @@ function request( remove_handle(downloader.multi, easy) close(easy.output) close(easy.progress) - interrupted = true + interrupted[] = true + close(input) + notify(easy.ready) end else interrupt_task = nothing @@ -425,7 +427,7 @@ function request( end end finally - if !interrupted + if !(interrupted[]) if interrupt_task !== nothing # trigger interrupt notify(interrupt) diff --git a/test/runtests.jl b/test/runtests.jl index f4b3ffb..75526c4 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -478,6 +478,17 @@ include("setup.jl") timedwait(()->istaskdone(download_task), 5.0) @test istaskdone(download_task) @test download_task.result isa RequestError + + interrupt = Base.Event() + url = "$server/put" + input=`sh -c 'sleep 15; echo "hello"'` + download_task = @async request(url; interrupt=interrupt, input=input) + sleep(0.1) + @test !istaskdone(download_task) + notify(interrupt) + timedwait(()->istaskdone(download_task), 5.0) + @test istaskdone(download_task) + @test download_task.result isa RequestError end @testset "progress" begin