Skip to content

Commit 1475273

Browse files
authored
Show full stacktrace when Channel Task throws (#35177)
This reuses the machinery that gives good stacktraces when a user calls wait on a Task. Since bind internally uses _wait2, this machinery is bypassed currently. Currently, julia throws an uninformative stacktrace in this situation: julia> c = Channel(_ -> error("foo")) Channel{Any}(sz_max:0,sz_curr:0) julia> for i in c end ERROR: foo Stacktrace: [1] iterate(::Channel{Any}) at ./channels.jl:459 [2] top-level scope at ./REPL[2]:1 With this change, the stacktrace is much more informative: julia> for i in c end ERROR: TaskFailedException: foo Stacktrace: [1] error(::String) at ./error.jl:33 [2] (::var"#1#2")(::Channel{Any}) at ./REPL[4]:1 [3] (::Base.var"#652#653"{var"#1#2",Channel{Any}})() at ./channels.jl:129 Stacktrace: [1] check_channel_state at ./channels.jl:167 [inlined] [2] take_unbuffered(::Channel{Any}) at ./channels.jl:405 [3] take! at ./channels.jl:383 [inlined] [4] iterate(::Channel{Any}, ::Nothing) at ./channels.jl:449 [5] iterate(::Channel{Any}) at ./channels.jl:448 [6] top-level scope at ./REPL[5]:1
1 parent b077c63 commit 1475273

File tree

4 files changed

+18
-15
lines changed

4 files changed

+18
-15
lines changed

base/channels.jl

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -228,15 +228,16 @@ false
228228
```jldoctest
229229
julia> c = Channel(0);
230230
231-
julia> task = @async (put!(c,1);error("foo"));
231+
julia> task = @async (put!(c, 1); error("foo"));
232232
233-
julia> bind(c,task);
233+
julia> bind(c, task);
234234
235235
julia> take!(c)
236236
1
237237
238-
julia> put!(c,1);
239-
ERROR: foo
238+
julia> put!(c, 1);
239+
ERROR: TaskFailedException:
240+
foo
240241
Stacktrace:
241242
[...]
242243
```
@@ -281,7 +282,7 @@ function close_chnl_on_taskdone(t::Task, c::Channel)
281282
if istaskfailed(t)
282283
excp = task_result(t)
283284
if excp isa Exception
284-
close(c, excp)
285+
close(c, TaskFailedException(t))
285286
return
286287
end
287288
end

test/channels.jl

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,9 @@ using Distributed
143143

144144
# Error exception in task
145145
c = Channel(N)
146-
bind(c, @async (GC.gc(); yield(); error("foo")))
147-
@test_throws ErrorException take!(c)
146+
task = @async (GC.gc(); yield(); error("foo"))
147+
bind(c, task)
148+
@test_throws TaskFailedException(task) take!(c)
148149
@test !isopen(c)
149150

150151
# Multiple channels closed by the same bound task
@@ -170,10 +171,11 @@ using Distributed
170171
while isopen(cs[i])
171172
yield()
172173
end
173-
@test_throws ErrorException wait(cs[i])
174-
@test_throws ErrorException take!(cs[i])
175-
@test_throws ErrorException put!(cs[i], 1)
176-
@test_throws ErrorException fetch(cs[i])
174+
@test_throws TaskFailedException(task) wait(cs[i])
175+
@test_throws TaskFailedException(task) take!(cs[i])
176+
@test_throws TaskFailedException(task) put!(cs[i], 1)
177+
N == 0 || @test_throws TaskFailedException(task) fetch(cs[i])
178+
N == 0 && @test_throws ErrorException fetch(cs[i])
177179
end
178180

179181
# Multiple tasks, first one to terminate closes the channel
@@ -245,10 +247,10 @@ using Distributed
245247
chnl = Channel{T}(tf6, N, taskref=taskref)
246248
put!(chnl, 2)
247249
yield()
248-
@test_throws ErrorException wait(chnl)
250+
@test_throws TaskFailedException(taskref[]) wait(chnl)
249251
@test istaskdone(taskref[])
250252
@test !isopen(chnl)
251-
@test_throws ErrorException take!(chnl)
253+
@test_throws TaskFailedException(taskref[]) take!(chnl)
252254
end
253255
end
254256

test/file.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1298,7 +1298,7 @@ cd(dirwalk) do
12981298
@test files == ["file1", "file2"]
12991299

13001300
rm(joinpath("sub_dir1"), recursive=true)
1301-
@test_throws SystemError take!(chnl_error) # throws an error because sub_dir1 do not exist
1301+
@test_throws TaskFailedException take!(chnl_error) # throws an error because sub_dir1 do not exist
13021302

13031303
root, dirs, files = take!(chnl_noerror)
13041304
@test root == "."

test/worlds.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ f265(::Int) = 1
138138
h265() = true
139139
loc_h265 = "$(@__FILE__):$(@__LINE__() - 1)"
140140
@test h265()
141-
@test_throws MethodError put_n_take!(h265, ())
141+
@test_throws TaskFailedException(t265) put_n_take!(h265, ())
142142
@test_throws TaskFailedException(t265) fetch(t265)
143143
@test istaskdone(t265)
144144
let ex = t265.exception

0 commit comments

Comments
 (0)