typelevel / typelevel/skunk

Pool$ResourceLeak in ScalaCheck Weaver suite

Open
#572 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Scala
Stars
1.7k
Forks
175
Avg merge
5d 14h
Merged PRs (30d)
9

Description

import cats.effect._
import skunk._
import skunk.implicits._
import natchez.Trace.Implicits.noop
import skunk.codec.text.text
import weaver.IOSuite
import weaver.scalacheck.{CheckConfig, Checkers}
import org.scalacheck.Gen

object SkunkWeaverSuite extends IOSuite with Checkers {

  type Res = Resource[IO, Session[IO]]

  // high count with low pool size (100, 1) triggers the issue consistently but will still trigger for 
  // low count / high pool size (1, 10), though not every time.
  override def checkConfig: CheckConfig = CheckConfig.default.copy(minimumSuccessful = 100)

  override def sharedResource: Resource[IO, Res] = {
    Session
      .pooled[IO](
        host = "localhost",
        port = 5432,
        user = "dev",
        database = "dev",
        max = 1,
      )
  }

  test("skunk") { pool =>
    forall(Gen.alphaNumStr)
    { _ =>
      pool.use {
        pg => pg.execute(sql"select version();".query(text)).map { v =>
//          println(s"Connected to Postgres $v")
          expect(!v.isEmpty) // irrelevant
        }
      }

    }
  }

}

[error] - Unexpected failure 0ms
[error]   Pool$ResourceLeak: 
[error]   🔥  
[error]   🔥  ResourceLeak
[error]   🔥  
[error]   🔥    Problem: A resource leak was detected during pool finalization.
[error]   🔥     Detail: Expected 1 active slot(s) and no deferrals, found 0 slots and 2
[error]   🔥             deferral(s).
[error]   🔥       Hint: The most common causes of resource leaks are (a) using a pool on a
[error]   🔥             fiber that was neither joined or canceled prior to pool finalization,
[error]   🔥             and (b) using `Resource.allocated` and failing to finalize allocated
[error]   🔥             resources prior to pool finalization.
[error]   🔥  
[error] 
[error]   skunk.util.Pool$ResourceLeak: A resource leak was detected during pool finalization.
[error] 
[error]   Pool.scala:156            skunk.util.Pool$#$anonfun$of$12
[error]   RunnerCompat.scala:225    void @ weaver.framework.RunnerCompat$ConcurrentQueueEventBroker#send
[error]   Pull.scala:1180           >>$extension @ fs2.Pull$#fs2$Pull$$go$1
[error]   Stream.scala:2047         complete @ fs2.Stream#$anonfun$parEvalMap$2
[error]   Stream.scala:2041         get @ fs2.Stream#$anonfun$parEvalMap$2
[error]   RunnerCompat.scala:158    parTraverse$extension @ weaver.framework.RunnerCompat#$anonfun$run$9
[error]   Stream.scala:2047         complete @ fs2.Stream#$anonfun$parEvalMap$2
[error]   Stream.scala:2041         get @ fs2.Stream#$anonfun$parEvalMap$2
[error]   RunnerCompat.scala:158    parTraverse$extension @ weaver.framework.RunnerCompat#$anonfun$run$9
[error]   RunnerCompat.scala:158    parTraverse$extension @ weaver.framework.RunnerCompat#$anonfun$run$9
[error]   RunnerCompat.scala:150    productR @ weaver.framework.RunnerCompat#$anonfun$run$9
[error]   RunnerCompat.scala:150    productR @ weaver.framework.RunnerCompat#$anonfun$run$9
[error]   Pool.scala:148            get @ skunk.util.Pool$#free$1

This proved to be an issue when Skunk is used with Weaver and ScalaCheck. Not sure who's at fault here but hopefully this issue will serve as a good starting point.

Starting sbt console and running test or ~test will produce this error on every single run, and querying for select count(*) from pg_stat_activity on psql will give an accumulated result += poolSize after each failed test run. Quitting and restarting sbt gets rid of the dangling connections.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the failure from the ScalaCheck Weaver suite by running sbt test, using the shared pooled Session and the stated pool and check counts. Then inspect skunk.util.Pool.scala around lines 148-156 and the Weaver RunnerCompat stack frames; done means identifying the responsible lifecycle interaction and preventing dangling connections after repeated test runs.

Written by the indexing model from the issue text.

Assessment

Tech stack
postgres, scala
Domain
databases, testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.