Skip to content

Commit

Permalink
fixup! fixup! fixup! Patch v8 to support promise cross-context resolu…
Browse files Browse the repository at this point in the history
…tion
  • Loading branch information
jasnell committed Sep 18, 2024
1 parent a5c9ee5 commit d1853b2
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/workerd/io/io-context.c++
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ IoContext::IoContext(ThreadContext& thread,
actor(actorParam),
limitEnforcer(kj::mv(limitEnforcerParam)),
threadId(getThreadId()),
deleteQueue(kj::atomicRefcounted<DeleteQueue>()),
deleteQueue(kj::atomicRefcounted<DeleteQueue>(), *this),
cachePutSerializer(kj::READY_NOW),
waitUntilTasks(*this),
timeoutManager(kj::heap<TimeoutManagerImpl>()),
Expand Down
23 changes: 23 additions & 0 deletions src/workerd/io/io-own.c++
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,29 @@ void DeleteQueue::scheduleAction(jsg::Lock& js, kj::Function<void(jsg::Lock&)>&&
}
}

DeleteQueuePtr::~DeleteQueuePtr() noexcept(false) {
auto ptr = get();
if (ptr != nullptr) {
auto lock = ptr->crossThreadDeleteQueue.lockExclusive();
// If there are actions still pending in the DeleteQueue, those will end up being
// silently dropped on the floor. This might cause some confusion for users who
// might expect promise continuations to still run. Let's log a warning in that
// case to help users understand what is happening.
KJ_IF_SOME(state, *lock) {
if (state.actions.size() > 0) {
context.logWarning(
"A promise was resolved or rejected from a different request context than "
"the one it was created in. However, the creating context is being destroyed "
"with continuations for that request still pending that can no longer be run "
"safely. This is usally because of the request being canceled or detected as "
"being hung.");
// TODO(soon): Add documentation link to this warning.
}
}
*lock = kj::none;
}
}

void DeleteQueue::checkFarGet(const DeleteQueue* deleteQueue, const std::type_info& type) {
IoContext::current().checkFarGet(deleteQueue, type);
}
Expand Down
16 changes: 8 additions & 8 deletions src/workerd/io/io-own.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,18 +222,18 @@ inline ReverseIoOwn<T> DeleteQueue::addObjectReverse(

// When the IoContext is destroyed, we need to null out the DeleteQueue. Complicating
// matters a bit, we need to cancel all tasks (destroy the TaskSet) before this happens, so
// we can't just do it in IoContext's destrucrtor. As a hack, we customize our pointer
// we can't just do it in IoContext's destructor. As a hack, we customize our pointer
// to the delete queue to get the tear-down order right.
class DeleteQueuePtr: public kj::Own<DeleteQueue> {
public:
DeleteQueuePtr(kj::Own<DeleteQueue> value): kj::Own<DeleteQueue>(kj::mv(value)) {}
DeleteQueuePtr(kj::Own<DeleteQueue> value, IoContext& context)
: kj::Own<DeleteQueue>(kj::mv(value)),
context(context) {}
KJ_DISALLOW_COPY_AND_MOVE(DeleteQueuePtr);
~DeleteQueuePtr() noexcept(false) {
auto ptr = get();
if (ptr != nullptr) {
*ptr->crossThreadDeleteQueue.lockExclusive() = kj::none;
}
}
~DeleteQueuePtr() noexcept(false);

private:
IoContext& context;
};

// Owned pointer held by a V8 heap object, pointing to a KJ event loop object. Cannot be
Expand Down

0 comments on commit d1853b2

Please sign in to comment.