effect
effect copied to clipboard
FiberHandle.clear looks racy ?
What version of Effect is running?
3.19.11
What steps can reproduce the bug?
See: https://github.com/Effect-TS/effect/blob/fb78c4061cec89718c49f842a91263a9bb8cf3cf/packages/effect/src/FiberHandle.ts#L317-L321
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