Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
C
capnproto
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
capnproto
Commits
23901780
Commit
23901780
authored
Jun 09, 2019
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix exclusiveJoin() bug when both branches complete simultaneously.
parent
729941e4
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
28 additions
and
6 deletions
+28
-6
async-test.c++
c++/src/kj/async-test.c++
+17
-0
async.c++
c++/src/kj/async.c++
+11
-6
No files found.
c++/src/kj/async-test.c++
View file @
23901780
...
...
@@ -809,5 +809,22 @@ TEST(Async, Poll) {
paf
.
promise
.
wait
(
waitScope
);
}
KJ_TEST
(
"exclusiveJoin both events complete simultaneously"
)
{
// Previously, if both branches of an exclusiveJoin() completed simultaneously, then the parent
// event could be armed twice. This is an error, but the exact results of this error depend on
// the parent PromiseNode type. One case where it matters is ArrayJoinPromiseNode, which counts
// events and decides it is done when it has received exactly the number of events expected.
EventLoop
loop
;
WaitScope
waitScope
(
loop
);
auto
builder
=
kj
::
heapArrayBuilder
<
kj
::
Promise
<
uint
>>
(
2
);
builder
.
add
(
kj
::
Promise
<
uint
>
(
123
).
exclusiveJoin
(
kj
::
Promise
<
uint
>
(
456
)));
builder
.
add
(
kj
::
NEVER_DONE
);
auto
joined
=
kj
::
joinPromises
(
builder
.
finish
());
KJ_EXPECT
(
!
joined
.
poll
(
waitScope
));
}
}
// namespace
}
// namespace kj
c++/src/kj/async.c++
View file @
23901780
...
...
@@ -945,14 +945,19 @@ bool ExclusiveJoinPromiseNode::Branch::get(ExceptionOrValue& output) {
}
Maybe
<
Own
<
Event
>>
ExclusiveJoinPromiseNode
::
Branch
::
fire
()
{
// Cancel the branch that didn't return first. Ignore exceptions caused by cancellation.
if
(
this
==
&
joinNode
.
left
)
{
kj
::
runCatchingExceptions
([
&
]()
{
joinNode
.
right
.
dependency
=
nullptr
;
});
if
(
dependency
)
{
// Cancel the branch that didn't return first. Ignore exceptions caused by cancellation.
if
(
this
==
&
joinNode
.
left
)
{
kj
::
runCatchingExceptions
([
&
]()
{
joinNode
.
right
.
dependency
=
nullptr
;
});
}
else
{
kj
::
runCatchingExceptions
([
&
]()
{
joinNode
.
left
.
dependency
=
nullptr
;
});
}
joinNode
.
onReadyEvent
.
arm
();
}
else
{
kj
::
runCatchingExceptions
([
&
]()
{
joinNode
.
left
.
dependency
=
nullptr
;
});
// The other branch already fired, and this branch was canceled. It's possible for both
// branches to fire if both were armed simultaneously.
}
joinNode
.
onReadyEvent
.
arm
();
return
nullptr
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment