-
-
Notifications
You must be signed in to change notification settings - Fork 475
Open
Labels
bugSomething isn't workingSomething isn't working
Description
What version of Effect is running?
3.19.11
What steps can reproduce the bug?
See:
effect/packages/effect/src/FiberHandle.ts
Lines 317 to 321 in fb78c40
| restore(Fiber.interruptAs(self.state.fiber, FiberId.combine(fiber.id(), internalFiberId))), | |
| Effect.sync(() => { | |
| if (self.state._tag === "Open") { | |
| self.state.fiber = undefined | |
| } |
export const clear = <A, E>(self: FiberHandle<A, E>): Effect.Effect<void> =>
Effect.uninterruptibleMask((restore) =>
Effect.withFiberRuntime((fiber) => {
if (self.state._tag === "Closed" || self.state.fiber === undefined) {
return Effect.void
}
return Effect.zipRight(
// This can suspend while waiting for the target fiber to actually terminate,
// which opens a window for another fiber to call FiberHandle.run/set.
restore(Fiber.interruptAs(self.state.fiber, FiberId.combine(fiber.id(), internalFiberId))),
Effect.sync(() => {
// If another fiber stored a new fiber into the handle while we were waiting above,
// this unconditional write can wipe out the newer reference.
if (self.state._tag === "Open") {
self.state.fiber = undefined
}
})
)
})
)clear interrupts the fiber currently stored in the handle and then waits for it to finish. While it’s waiting, another fiber can call FiberHandle.run / set and put a new fiber into the handle. When clear continues, it blindly does state.fiber = undefined, which can wipe out the newer fiber reference.
So the handle can appear empty (e.g. unsafeGet returns None / get fails) even though the newer fiber is still running, meaning the handle has lost the reference and can no longer cancel/manage that fiber.
perhaps a fix like this:
export const clear = <A, E>(self: FiberHandle<A, E>): Effect.Effect<void> =>
Effect.uninterruptibleMask((restore) =>
Effect.withFiberRuntime((runtimeFiber) => {
if (self.state._tag === "Closed" || self.state.fiber === undefined) {
return Effect.void
}
const target = self.state.fiber
return Effect.zipRight(
restore(Fiber.interruptAs(target, FiberId.combine(runtimeFiber.id(), internalFiberId))),
Effect.sync(() => {
if (self.state._tag === "Open" && self.state.fiber === target) {
self.state.fiber = undefined
}
})
)
})
)What is the expected behavior?
No response
What do you see instead?
No response
Additional information
No response
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working