Description
Conditions: Ubuntu/MacOS, Julia 1.7.1/1.6.5
Related issues: #94 , #110
Note: the examples here are MRE's and are not what the troublesome code looks like. It seems like a multi-threaded julia application calling Azure/Downloads suffers sporadically from this issue.
The error looks like this(where the last 3 lines repeat seemingly forever):
From worker 4: ┌ Error: 2022-03-14T16:11:24.498 (txn_id: 1044876555423232961)
From worker 4: │ curl_multi_socket_action: 8
From worker 4: └ @ Downloads.Curl /build/source/usr/share/julia/stdlib/v1.7/Downloads/src/Curl/utils.jl:36
Can sometimes reproduce with: JULIA_NUM_THREADS=4 julia171
using Downloads
Threads.@threads for url in ["1","2","3","4","5","6","7","8"]
open("/tmp/cool$url", "w") do io
resp = Downloads.request("http://google.com"; output=io, method="GET")
end
end
If this does not reproduce the curl_multi_socket_action
bug rerun the Threads.@threads loop until it happens (typically takes 1-5 executions).
Also sporadically reproduces without the explicit I/O scope/pattern with the same frequency, ie:
using Downloads
Threads.@threads for url in ["1","2","3","4","5","6","7","8"]
resp = Downloads.request("http://google.com"; output="/tmp/cool_$url", method="GET")
end
Maybe more/less interesting: without the output field(ie: Downloads.request("http://google.com"; method="GET")
) there is another nondeterministic error that infrequently occurs..:
ERROR: TaskFailedException
Stacktrace:
[1] wait
@ ./task.jl:334 [inlined]
[2] threading_run(func::Function)
@ Base.Threads ./threadingconstructs.jl:38
[3] top-level scope
@ ./threadingconstructs.jl:97
nested task error: val already in a list
Stacktrace:
[1] try_yieldto(undo::typeof(Base.ensure_rescheduled))
@ Base ./task.jl:777
[2] wait()
@ Base ./task.jl:837
[3] wait(c::Base.GenericCondition{ReentrantLock})
@ Base ./condition.jl:123
[4] take_buffered(c::Channel{Any})
@ Base ./channels.jl:389
[5] take!
@ ./channels.jl:383 [inlined]
[6] sync_end(c::Channel{Any})
@ Base.Experimental ./experimental.jl:64
[7] macro expansion
@ ./experimental.jl:102 [inlined]
[8] (::Downloads.var"#9#18"{Base.DevNull, Base.DevNull, String, Vector{Pair{String, String}}, Float64, Nothing, Bool, Bool, String, Int64, Bool, Bool})(easy::Downloads.Curl.Easy)
@ Downloads ~/julia-1.7.1/share/julia/stdlib/v1.7/Downloads/src/Downloads.jl:347
[9] with_handle(f::Downloads.var"#9#18"{Base.DevNull, Base.DevNull, String, Vector{Pair{String, String}}, Float64, Nothing, Bool, Bool, String, Int64, Bool, Bool}, handle::Downloads.Curl.Easy)
@ Downloads.Curl ~/julia-1.7.1/share/julia/stdlib/v1.7/Downloads/src/Curl/Curl.jl:64
[10] #8
@ ~/julia-1.7.1/share/julia/stdlib/v1.7/Downloads/src/Downloads.jl:311 [inlined]
[11] arg_write(f::Downloads.var"#8#17"{Base.DevNull, String, Vector{Pair{String, String}}, Float64, Nothing, Bool, Bool, String, Int64, Bool, Bool}, arg::Base.DevNull)
@ ArgTools ~/julia-1.7.1/share/julia/stdlib/v1.7/ArgTools/src/ArgTools.jl:112
[12] #7
@ ~/julia-1.7.1/share/julia/stdlib/v1.7/Downloads/src/Downloads.jl:310 [inlined]
[13] arg_read
@ ~/julia-1.7.1/share/julia/stdlib/v1.7/ArgTools/src/ArgTools.jl:61 [inlined]
[14] request(url::String; input::Nothing, output::Nothing, method::String, headers::Vector{Pair{String, String}}, timeout::Float64, progress::Nothing, verbose::Bool, throw::Bool, downloader::Nothing)
@ Downloads ~/julia-1.7.1/share/julia/stdlib/v1.7/Downloads/src/Downloads.jl:309
[15] macro expansion
@ ./REPL[2]:2 [inlined]
[16] (::var"#124#threadsfor_fun#9"{Vector{String}})(onethread::Bool)
@ Main ./threadingconstructs.jl:85
[17] (::var"#124#threadsfor_fun#9"{Vector{String}})()
@ Main ./threadingconstructs.jl:52
Any help or guidance appreciated