Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finalizer being called early on fin IORef #28

Open
lunaris opened this issue Jun 13, 2016 · 0 comments
Open

Finalizer being called early on fin IORef #28

lunaris opened this issue Jun 13, 2016 · 0 comments

Comments

@lunaris
Copy link

lunaris commented Jun 13, 2016

When using pool to manage a series of PostgreSQL connections (via postgresql-simple), I've found that idle connections are not being reaped. After doing some digging, it appears that the reaper thread is being killed almost immediately, which I've linked to the execution of the finaliser attached to the internal fin IORef. I've no doubt that this is an issue with my code and not pool, but was wondering if I might find some help here. While I've not managed to produce a minimal reproducing test case, I have details about what I'm doing:

  • I'm wrapping the pool in a newtype, as in newtype MyPool = MyPool (Pool PG.Connection) and building one with fmap viz.
MyPool <$>
  createPool PG.createConnection PG.closeConnection noOfStripes maxIdleTime perStripe
  • The above function results in the following core. To my inexperienced eyes, it doesn't suggest any cheeky unpacking/losing of the IORef by GHC (which to my inexperienced brain is what would trigger a GHC and subsequent finalizer running, no?):
createPostgreSQLConnectionPool
  :: PostgreSQLConfiguration
     -> PostgreSQLConnectionPoolConfiguration
     -> IO PostgreSQLConnectionPool
[GblId, Arity=2, Str=DmdType]
createPostgreSQLConnectionPool =
  \ (ds_doFL :: PostgreSQLConfiguration)
    (ds1_doFM :: PostgreSQLConnectionPoolConfiguration) ->
    case ds_doFL
    of _ [Occ=Dead]
    { PostgreSQLConfiguration ds2_doFN ds3_doFO ds4_doFP ds5_doFQ
                              ds6_doFR ->
    case ds1_doFM
    of _ [Occ=Dead]
    { PostgreSQLConnectionPoolConfiguration ds7_doFS ds8_doFT
                                            ds9_doFU ->
    let {
      closePostgreSQL_anEf :: PG.Connection -> IO ()
      [LclId, Str=DmdType]
      closePostgreSQL_anEf =
        \ (conn_anEg :: PG.Connection) ->
          >>
            @ IO
            GHC.Base.$fMonadIO
            @ ()
            @ ()
            (putStrLn
               (ghc-prim-0.4.0.0:GHC.CString.unpackCString#
                  "[PG] Closing connection"#))
            (PG.close conn_anEg) } in
    let {
      connectToPostgreSQL'_anEe :: IO PG.Connection
      [LclId, Str=DmdType]
      connectToPostgreSQL'_anEe =
        >>
          @ IO
          GHC.Base.$fMonadIO
          @ ()
          @ PG.Connection
          (putStrLn
             (ghc-prim-0.4.0.0:GHC.CString.unpackCString#
                "[PG] Creating connection"#))
          (PG.connect
             (case PG.defaultConnectInfo
              of _ [Occ=Dead]
              { PG.ConnectInfo ds10_doG0 ds11_doG1 ds12_doG2 ds13_doG3
                               ds14_doG4 ->
              Database.PostgreSQL.Simple.Internal.ConnectInfo
                ds2_doFN
                (fromIntegral
                   @ Int
                   @ GHC.Word.Word16
                   GHC.Real.$fIntegralInt
                   GHC.Word.$fNumWord16
                   ds3_doFO)
                ds4_doFP
                ds5_doFQ
                ds6_doFR
              })) } in
    <$>
      @ (Pool.Pool PG.Connection)
      @ PostgreSQLConnectionPool
      @ IO
      GHC.Base.$fFunctorIO
      ((\ (tpl_B1 :: Pool.Pool PG.Connection) -> tpl_B1)
       `cast` (<Pool.Pool PG.Connection>_R
               -> Sym
                    Company.PostgreSQL.Internal.Trans.NTCo:PostgreSQLConnectionPool[0]
               :: (Pool.Pool PG.Connection -> Pool.Pool PG.Connection)
                  ~R# (Pool.Pool PG.Connection -> PostgreSQLConnectionPool)))
      (Pool.createPool
         @ PG.Connection
         connectToPostgreSQL'_anEe
         closePostgreSQL_anEf
         ds7_doFS
         (fromIntegral
            @ Int
            @ time-1.5.0.1:Data.Time.Clock.UTC.NominalDiffTime
            GHC.Real.$fIntegralInt
            time-1.5.0.1:Data.Time.Clock.UTC.$fNumNominalDiffTime
            ds8_doFT)
         ds9_doFU)
    }
    }
  • The created pool is being used to run a transformer stack, as in runPostgreSQL pool, and is working just fine in every other regard, so it seems like the fin is the only part of the structure being GC'd (again, assuming that this is the cause of the finaliser's running).
  • To be clear, removing the call to mkWeakIORef causes the reaper to work correctly. Furthermore, the local pool finalizers can be left in place without affecting its working. Lastly, using addFinalizer from System.Mem.Weak (as was done in a previous version of this library, I believe) does not help either (again, perhaps it was stupid to assume it would).

Thanks in advance for any advice and apologies for not providing a minimal working example; I am struggling to find out exactly what I'm doing that's causing this. If there is any other information I can provide in the mean time I am happy to oblige to try and crack this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant