Skip to content

fix: propagate bound task exceptions in iterate#5

Merged
zsoerenm merged 1 commit into
mainfrom
ss/fix-exception-propagation
Jan 19, 2026
Merged

fix: propagate bound task exceptions in iterate#5
zsoerenm merged 1 commit into
mainfrom
ss/fix-exception-propagation

Conversation

@zsoerenm

Copy link
Copy Markdown
Member

Match Julia's Channel behavior: when iterating over a closed channel, check for stored exceptions from bound tasks and throw them instead of silently returning nothing.

Previously, if a bound task failed with an exception, iterate() would catch the InvalidStateException from take!() and return nothing, swallowing the original exception. Now we check ch.excp and propagate the stored exception if present.

This ensures errors in producer tasks properly surface to consumers iterating over the channel.

Match Julia's Channel behavior: when iterating over a closed channel,
check for stored exceptions from bound tasks and throw them instead of
silently returning nothing.

Previously, if a bound task failed with an exception, iterate() would
catch the InvalidStateException from take!() and return nothing,
swallowing the original exception. Now we check ch.excp and propagate
the stored exception if present.

This ensures errors in producer tasks properly surface to consumers
iterating over the channel.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@zsoerenm zsoerenm self-assigned this Jan 19, 2026
@zsoerenm
zsoerenm enabled auto-merge (rebase) January 19, 2026 12:22
@zsoerenm
zsoerenm merged commit eb5b868 into main Jan 19, 2026
6 checks passed
@codecov

codecov Bot commented Jan 19, 2026

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

@github-actions

Copy link
Copy Markdown

Benchmark Results (Julia v1)

Time benchmarks
main ea77dd1... main / ea77dd1...
batch/batch=128 26.7 ± 0.41 μs 26.8 ± 0.34 μs 0.999 ± 0.02
batch/batch=16 0.0401 ± 0.00048 ms 0.0402 ± 0.00069 ms 0.998 ± 0.021
batch/batch=256 27.3 ± 3.5 μs 26.4 ± 3.4 μs 1.04 ± 0.19
batch/batch=32 0.0324 ± 0.0077 ms 0.0323 ± 0.0005 ms 1 ± 0.24
batch/batch=64 28.3 ± 0.42 μs 28.5 ± 8.1 μs 0.992 ± 0.28
batch/batch=8 0.0671 ± 0.009 ms 0.0587 ± 0.00061 ms 1.14 ± 0.15
batch/put!_batch=128 0.18 ± 0.02 μs 0.18 ± 0.02 μs 1 ± 0.16
batch/put!_batch=16 0.04 ± 0 μs 0.04 ± 0 μs 1 ± 0
batch/put!_batch=256 0.21 ± 0.069 μs 0.21 ± 0.06 μs 1 ± 0.44
batch/put!_batch=32 0.13 ± 0.1 μs 0.05 ± 0.002 μs 2.6 ± 2
batch/put!_batch=64 0.151 ± 0.019 μs 0.15 ± 0.02 μs 1.01 ± 0.18
batch/put!_batch=8 0.04 ± 0.01 μs 0.04 ± 0.01 μs 1 ± 0.35
batch/single 0.154 ± 0.031 ms 0.158 ± 0.031 ms 0.977 ± 0.28
batch/take!_batch=128 0.1 ± 0.01 μs 0.11 ± 0.011 μs 0.909 ± 0.13
batch/take!_batch=16 0.05 ± 0.01 μs 0.06 ± 0.01 μs 0.833 ± 0.22
batch/take!_batch=256 0.351 ± 0.1 μs 0.341 ± 0.1 μs 1.03 ± 0.42
batch/take!_batch=32 0.06 ± 0.01 μs 0.07 ± 0.01 μs 0.857 ± 0.19
batch/take!_batch=64 0.08 ± 0.01 μs 0.08 ± 0.01 μs 1 ± 0.18
batch/take!_batch=8 0.05 ± 0.001 μs 0.05 ± 0.01 μs 1 ± 0.2
batch/take!_buffer_batch=128 0.081 ± 0.01 μs 0.09 ± 0.001 μs 0.9 ± 0.11
batch/take!_buffer_batch=16 0.04 ± 0 μs 0.04 ± 0 μs 1 ± 0
batch/take!_buffer_batch=256 0.17 ± 0.07 μs 0.17 ± 0.069 μs 1 ± 0.58
batch/take!_buffer_batch=32 0.05 ± 0.01 μs 0.05 ± 0 μs 1 ± 0.2
batch/take!_buffer_batch=64 0.06 ± 0 μs 0.07 ± 0.01 μs 0.857 ± 0.12
batch/take!_buffer_batch=8 0.04 ± 0.01 μs 0.04 ± 0.01 μs 1 ± 0.35
channel/buffer=1 5.15 ± 0.041 ms 5.1 ± 0.042 ms 1.01 ± 0.012
channel/buffer=1024 0.651 ± 0.022 ms 0.64 ± 0.023 ms 1.02 ± 0.05
channel/buffer=16 0.928 ± 0.011 ms 0.924 ± 0.014 ms 1 ± 0.019
channel/buffer=256 0.646 ± 0.011 ms 0.635 ± 0.014 ms 1.02 ± 0.028
channel/buffer=4 1.79 ± 0.018 ms 1.78 ± 0.018 ms 1 ± 0.014
channel/buffer=64 0.693 ± 0.013 ms 0.688 ± 0.012 ms 1.01 ± 0.025
channel/put! 0.08 ± 0.009 μs 0.08 ± 0.009 μs 1 ± 0.16
channel/take! 0.051 ± 0.01 μs 0.06 ± 0.01 μs 0.85 ± 0.22
pipechannel/buffer=1 3.89 ± 0.049 ms 3.89 ± 0.048 ms 0.999 ± 0.017
pipechannel/buffer=1024 0.15 ± 0.031 ms 0.153 ± 0.0083 ms 0.98 ± 0.21
pipechannel/buffer=16 0.385 ± 0.01 ms 0.389 ± 0.014 ms 0.989 ± 0.044
pipechannel/buffer=256 0.168 ± 0.0075 ms 0.171 ± 0.0087 ms 0.979 ± 0.066
pipechannel/buffer=4 1.07 ± 0.021 ms 1.08 ± 0.022 ms 0.992 ± 0.028
pipechannel/buffer=64 0.213 ± 0.0085 ms 0.224 ± 0.007 ms 0.951 ± 0.048
pipechannel/put! 30 ± 1 ns 30 ± 1 ns 1 ± 0.047
pipechannel/take! 30 ± 1 ns 30 ± 1 ns 1 ± 0.047
time_to_load 0.0329 ± 0.00016 s 0.0329 ± 0.00042 s 1 ± 0.014
Memory benchmarks
main ea77dd1... main / ea77dd1...
batch/batch=128 15 allocs: 2.91 kB 15 allocs: 2.91 kB 1
batch/batch=16 15 allocs: 1.09 kB 15 allocs: 1.09 kB 1
batch/batch=256 17 allocs: 4.86 kB 17 allocs: 4.86 kB 1
batch/batch=32 15 allocs: 1.34 kB 15 allocs: 1.34 kB 1
batch/batch=64 15 allocs: 1.84 kB 15 allocs: 1.84 kB 1
batch/batch=8 15 allocs: 0.969 kB 15 allocs: 0.969 kB 1
batch/put!_batch=128 0 allocs: 0 B 0 allocs: 0 B
batch/put!_batch=16 0 allocs: 0 B 0 allocs: 0 B
batch/put!_batch=256 0 allocs: 0 B 0 allocs: 0 B
batch/put!_batch=32 0 allocs: 0 B 0 allocs: 0 B
batch/put!_batch=64 0 allocs: 0 B 0 allocs: 0 B
batch/put!_batch=8 0 allocs: 0 B 0 allocs: 0 B
batch/single 11 allocs: 0.703 kB 11 allocs: 0.703 kB 1
batch/take!_batch=128 2 allocs: 1.09 kB 2 allocs: 1.09 kB 1
batch/take!_batch=16 2 allocs: 0.188 kB 2 allocs: 0.188 kB 1
batch/take!_batch=256 3 allocs: 2.07 kB 3 allocs: 2.07 kB 1
batch/take!_batch=32 2 allocs: 0.312 kB 2 allocs: 0.312 kB 1
batch/take!_batch=64 2 allocs: 0.562 kB 2 allocs: 0.562 kB 1
batch/take!_batch=8 2 allocs: 0.125 kB 2 allocs: 0.125 kB 1
batch/take!_buffer_batch=128 0 allocs: 0 B 0 allocs: 0 B
batch/take!_buffer_batch=16 0 allocs: 0 B 0 allocs: 0 B
batch/take!_buffer_batch=256 0 allocs: 0 B 0 allocs: 0 B
batch/take!_buffer_batch=32 0 allocs: 0 B 0 allocs: 0 B
batch/take!_buffer_batch=64 0 allocs: 0 B 0 allocs: 0 B
batch/take!_buffer_batch=8 0 allocs: 0 B 0 allocs: 0 B
channel/buffer=1 12 allocs: 0.75 kB 12 allocs: 0.75 kB 1
channel/buffer=1024 19 allocs: 17.2 kB 19 allocs: 17.2 kB 1
channel/buffer=16 14 allocs: 1.14 kB 14 allocs: 1.14 kB 1
channel/buffer=256 17 allocs: 6.51 kB 17 allocs: 6.51 kB 1
channel/buffer=4 13 allocs: 0.844 kB 13 allocs: 0.844 kB 1
channel/buffer=64 15 allocs: 2.28 kB 15 allocs: 2.28 kB 1
channel/put! 1 allocs: 0.0469 kB 1 allocs: 0.0469 kB 1
channel/take! 0 allocs: 0 B 0 allocs: 0 B
pipechannel/buffer=1 11 allocs: 0.703 kB 11 allocs: 0.703 kB 1
pipechannel/buffer=1024 11 allocs: 0.703 kB 11 allocs: 0.703 kB 1
pipechannel/buffer=16 11 allocs: 0.703 kB 11 allocs: 0.703 kB 1
pipechannel/buffer=256 11 allocs: 0.703 kB 11 allocs: 0.703 kB 1
pipechannel/buffer=4 11 allocs: 0.703 kB 11 allocs: 0.703 kB 1
pipechannel/buffer=64 11 allocs: 0.703 kB 11 allocs: 0.703 kB 1
pipechannel/put! 0 allocs: 0 B 0 allocs: 0 B
pipechannel/take! 0 allocs: 0 B 0 allocs: 0 B
time_to_load 0.145 k allocs: 11 kB 0.145 k allocs: 11 kB 1

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

Successfully merging this pull request may close these issues.

1 participant