Skip to content

Commit 9352ada

Browse files
committed
New issue from Eric Niebler: schedule_from isn't starting the schedule sender if decay-copying results throws
1 parent 8f6dfaf commit 9352ada

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed

xml/issue4198.xml

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?xml version='1.0' encoding='utf-8' standalone='no'?>
2+
<!DOCTYPE issue SYSTEM "lwg-issue.dtd">
3+
4+
<issue num="4198" status="New">
5+
<title>`schedule_from` isn't starting the schedule sender if decay-copying results throws</title>
6+
<section><sref ref="[exec.schedule.from]"/></section>
7+
<submitter>Eric Niebler</submitter>
8+
<date>03 Feb 2025</date>
9+
<priority>99</priority>
10+
11+
<discussion>
12+
<p>
13+
Imported from <a href="https://github.com/cplusplus/sender-receiver/issues/304">cplusplus/sender-receiver #304</a>.
14+
</p>
15+
<p>
16+
<sref ref="[exec.schedule.from]"/>/p11 specifies `shedule_from`'s completion operation as follows:
17+
18+
<pre><code>
19+
[]&lt;class Tag, class... Args&gt;(auto, auto&amp; state, auto&amp; rcvr, Tag, Args&amp;&amp;... args) noexcept
20+
-> void {
21+
using result_t = decayed-tuple&lt;Tag, Args...&gt;;
22+
constexpr bool nothrow = is_nothrow_constructible_v&lt;result_t, Tag, Args...&gt;;
23+
24+
try {
25+
state.async-result.template emplace&lt;result_t&gt;(Tag(), std::forward&lt;Args&gt;(args)...);
26+
} catch (...) {
27+
if constexpr (!nothrow) {
28+
set_error(std::move(rcvr), current_exception());
29+
return;
30+
}
31+
}
32+
start(state.op-state);
33+
};
34+
</code></pre>
35+
36+
so if emplacing the result tuple throws, `set_error` is immediately called on the downstream receiver. no attempt is made to post the completion to the specified scheduler. this is probably not the right behavior.
37+
</p>
38+
<p><b>Suggested resolution</b></p>
39+
<p>
40+
The right thing, i think, is to catch the exception, emplace the `exception_ptr` into the <i>`async-result`</i> variant, and then start the schedule operation, as shown below:
41+
42+
<pre><code>
43+
[]&lt;class Tag, class... Args&gt;(auto, auto&amp; state, auto&amp; rcvr, Tag, Args&amp;&amp;... args) noexcept
44+
-> void {
45+
using result_t = decayed-tuple&lt;Tag, Args...&gt;;
46+
constexpr bool nothrow = is_nothrow_constructible_v&lt;result_t, Tag, Args...&gt;;
47+
48+
try {
49+
state.async-result.template emplace&lt;result_t&gt;(Tag(), std::forward&lt;Args&gt;(args)...);
50+
} catch(...) {
51+
if constexpr (nothrow)
52+
state.async-result.template emplace&lt;tuple&lt;set_error_t, exception_ptr&gt;&gt;(set_error, current_exception());
53+
}
54+
}
55+
56+
start(state.op-state);
57+
}
58+
</code></pre>
59+
60+
we also need to change how we specify the variant type of `state.async-result`:
61+
62+
<blockquote>
63+
Let `Sigs` be a pack of the arguments to the `completion_signatures`
64+
specialization named by
65+
`completion_signatures_of_t<child-type<Sndr>, env_of_t<Rcvr>>`.
66+
Let <i><code>as-tuple</code></i> be an alias template
67+
<del>
68+
that transforms a completion signature `Tag(Args...)` into
69+
the tuple specialization `decayed-tuple<Tag, Args...>`.
70+
</del>
71+
<ins>
72+
such that `as-tuple<Tag(Args...)>` denotes
73+
the tuple specialization `decayed-tuple<Tag, Args...>`,
74+
and let is-nothrow-decay-copy-sig be
75+
a variable template such that
76+
<code>is-nothrow-decay-copy-sig&lt;Tag(Args...)&gt;</code>
77+
is a core constant expression of type `bool const` and whose value
78+
is `true` if the types `Args...` are all nothrow decay-copyable, and `false`
79+
otherwise.
80+
Let <i><code>error-completion</code></i> be a pack consisting of the type
81+
`set_error_t(exception_ptr)` if
82+
<code>(is-nothrow-decay-copy-sig&lt;Sigs&gt; &amp;&amp;...)</code>
83+
is `false`, and an empty pack otherwise.
84+
</ins>
85+
Then `variant_t` denotes the type
86+
<code>variant&lt;monostate, as-tuple&lt;Sigs&gt;...<ins>, <i>error-completion</i>...</ins>&gt;</code>,
87+
except with duplicate types removed.
88+
</blockquote>
89+
90+
</p>
91+
</discussion>
92+
93+
<resolution>
94+
<p>
95+
</p>
96+
</resolution>
97+
98+
</issue>

0 commit comments

Comments
 (0)