Commit 23901780 authored by Kenton Varda's avatar Kenton Varda

Fix exclusiveJoin() bug when both branches complete simultaneously.

parent 729941e4
......@@ -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
......@@ -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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment