Repository navigation
Conversation
…ails or is stopped
`merge_each` connects each item of the input sequence, which is a sender
of a nested sequence, to `__receive_nested_sequence`. When that sender
completed with `set_error` or `set_stopped`, or when subscribing to the
nested sequence threw, the receiver only updated the bookkeeping of the
`merge_each` operation and never completed the next receiver of the
input sequence. The input sequence was left waiting for that item, so
the `merge_each` operation never completed. For example,
merge_each(just(1) | then([](int) -> decltype(just(0)) { throw 42; }))
| ignore_all_values()
never called its receiver, and a stop request that arrived between two
nested sequences of `merge_each(iterate(...) | transform_each(...))`
was lost in the same way.
This diff completes the next receiver in those three places, as
`__receive_nested_values` already does once a nested sequence has been
subscribed. An error breaks the input sequence and is delivered as the
last item, like the errors of nested sequences. A stopped sender is
skipped, unless stop has been requested, in which case the input
sequence is asked to stop too.
The new tests cover an erroring sender, a stopped sender, a throwing
`subscribe`, and a stop request between nested sequences.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Signed-off-by: Dezhen Lu <dezhen.lu@student.uni-tuebingen.de>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2445
exec::merge_eachnever completes if an item of the input sequence (a sender of a nested sequence) completes withset_errororset_stopped, or ifsubscribeon the nested sequence throws. In those three places__receive_nested_sequencecalled__op_->nested_sequence_break()/__op_->nested_sequence_complete(), which update the state of themerge_eachoperation but don't complete the input sequence's next receiver. The input sequence then waits for that item forever. For example, this hangs insync_wait:A stop request that arrives between two nested sequences of
merge_each(iterate(...) | transform_each(...))is lost in the same way, because the sender of the next nested sequence is then stopped.This change completes the next receiver through
__next_seq_op_, as__receive_nested_valuesalready does:subscribe): the error is stored, the next receiver getsset_stopped, and the error is delivered as the last item, like the errors of nested sequences (Fix merge_each error propagation #2175);set_value, so the stopped sender is skipped and the rest is merged; if stop has been requested, the next receiver getsset_stoppedso that the input sequence stops too.Tests
Added to
test/exec/sequence/test_merge_each.cpp; all four fail without the change inmerge_each.hpp:merge_each - completes when the sender of a nested sequence failsmerge_each - continues when the sender of a nested sequence is stoppedmerge_each - completes with stopped when stop is requested between nested sequencesmerge_each - completes when subscribing to a nested sequence throwsRun on x86_64 Linux, Debug, C++20, with the branch based on f71dc7d:
test.exec "merge_each*"on main + new teststest.execwith the fixclang-format 21.1.8 reports no violations on the two changed files. libc++, gcc 12/14/15, MSVC,
-fno-exceptions, the sanitizer rows and the modules build were not run locally.The branch was then rebased onto a8449ab (the two new commits on main don't touch these files) and the test suite was not rebuilt after the rebase. The reproducer from the issue was re-run at a8449ab with Apple clang 21 on arm64 macOS: all three operations never complete on main and complete with this change.
Open point
When the sender is stopped and no stop was requested, this skips it and continues with the next nested sequence. If you would rather end the input sequence in that case, it is a one-line change.
AI disclosure
Claude Code, model claude-fable-5-2; AI was used to find the bug, write the reproducer, write the fix and the tests, run the tests listed above, and draft this description (the rebase and the re-run at a8449ab were done with Claude Code, claude-opus-5-5); AI-generated code:
include/exec/sequence/merge_each.hpp(the changes in__receive_nested_sequence, +16/−3) andtest/exec/sequence/test_merge_each.cpp(the four new test cases and their helpers, +128).🤖 Generated with Claude Code