Skip to content

Fix: when_all cancelled from environment - #1718

Merged
ericniebler merged 2 commits into
NVIDIA:mainfrom
sithhell:fix/when_all_stop
Dec 19, 2025
Merged

ericniebler merged 2 commits into
NVIDIA:mainfrom
sithhell:fix/when_all_stop

Conversation

@sithhell

Copy link
Copy Markdown
Contributor

In the case when when_all is being stopped from a stop source in the environment, the stop_source was triggered multiple times leading to a use after free bug.

This patch fixes this by performing the following steps:

  • Inside the stop callback, increment the reference count.
  • Try setting the state to stopped, only if stopped, trigger the internal stop_source which cancels the children.
  • Arrive to decrement the count again and handle any concurrent completions if needed.

In the case when when_all is being stopped from a stop source in the
environment, the stop_source was triggered multiple times leading to a
use after free bug.

This patch fixes this by performing the following steps:

 - Inside the stop callback, increment the reference count.
 - Try setting the state to stopped, only if stopped, trigger the
   internal stop_source which cancels the children.
 - Arrive to decrement the count again and handle any concurrent
   completions if needed.
@copy-pr-bot

copy-pr-bot Bot commented Dec 17, 2025

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@ericniebler

Copy link
Copy Markdown
Collaborator

/ok to test 1982e32

Comment thread include/stdexec/__detail/__when_all.hpp Resolved
Comment thread include/stdexec/__detail/__when_all.hpp Resolved
@ericniebler

Copy link
Copy Markdown
Collaborator

/ok to test 75c45fb

@ericniebler
ericniebler merged commit 36a92fd into NVIDIA:main Dec 19, 2025
26 of 28 checks passed
@sithhell
sithhell deleted the fix/when_all_stop branch December 19, 2025 08:09
gamecentric pushed a commit to gamecentric/stdexec that referenced this pull request Mar 29, 2026
* Fix: when_all cancelled from environment

In the case when when_all is being stopped from a stop source in the
environment, the stop_source was triggered multiple times leading to a
use after free bug.

This patch fixes this by performing the following steps:

 - Inside the stop callback, increment the reference count.
 - Try setting the state to stopped, only if stopped, trigger the
   internal stop_source which cancels the children.
 - Arrive to decrement the count again and handle any concurrent
   completions if needed.

* use atomics from `stdexec::__std::` instead of `std::`

---------

Co-authored-by: Eric Niebler <[email protected]>
ericniebler pushed a commit to ericniebler/stdexec that referenced this pull request Oct 25, 2026
The stop callbacks that when_all (since NVIDIA#1718) and exec::when_any (since
NVIDIA#2115) register on the receiver's stop token increment the count of
outstanding children, request stop, and then arrive. If the last child
arrives on another thread while such a callback is running, the count is
already zero, so the callback's arrival completes the operation a second
time. With inplace_stop_source the thread of the last child usually
spins forever in ~inplace_stop_callback instead, waiting for a callback
that the other thread has already destroyed.

The extra count only worked around inplace_stop_source not tolerating
its destruction from inside its own request_stop() (NVIDIA#1889), which NVIDIA#2303
fixed. Make both callbacks only forward the request to the internal stop
source, like on-stop-request in [exec.when.all]. For when_all this also
undoes the rest of the workaround from NVIDIA#1851: it completes with
set_stopped only when a child does, and it no longer records values once
a child has failed or been stopped.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
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.

2 participants