take can silently drop a pooled resource when cancelled
Nobody has claimed this yet.
- Dominant language
- Scala
- Stars
- 39
- Forks
- 18
- Avg merge
- 8h 26m
- Merged PRs (30d)
- 4
Description
KeyPool.take can lose a pooled resource entirely if the caller is cancelled at the wrong moment. The resource is neither destroyed nor returned to the pool, so whatever it wraps leaks.
The resource comes out of the pool map here:
optR <- Resource.eval(kp.kpVar.modify(go))
releasedState <- Resource.eval(Ref[F].of[Reusable](kp.kpDefaultReuseState))
resource <- Resource.makeFull[F, (B, F[Unit])] { poll => ... }
Resource.fold interprets Eval as a plain fa.flatMap(...), no bracket and no mask, and all of this sits in the permit's polled use position. So between modify(go) committing and makeFull entering its uncancelable region, the resource exists only in a flatMap continuation. Cancel there and it's gone.
The annoying part is that nothing looks broken afterwards. The permit is released correctly and the idle count is decremented correctly, so pool state stays consistent. You just lose the resource without the destroy hook ever running, which is why this shows up as leaked file descriptors with nothing in the pool metrics to explain it.
Repro: https://gist.github.com/stasimus/3d9b0d6eedcae885b410cac0a7e040dd#file-takecancelspec-scala
Not reachable under TestControl. take is straight-line between the modify and the bracket, so a deterministic single-threaded scheduler never interleaves a cancel there. 500 replications, zero hits.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at KeyPool.take, particularly the kpVar.modify(go), Resource.makeFull, and Resource.fold sequence described in the issue. Run the linked takecancelspec.scala reproduction and verify that cancellation cannot lose the pooled resource or skip its destroy hook, while permit release and idle-count behavior remain correct.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- scala
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100