Open parsonsmatt opened 1 month ago
I cannot follow in detail. But if rmLoggerSet
is called, fd
should be closed since rmLoggerSet
is defined as follows:
rmLoggerSet :: LoggerSet -> IO ()
rmLoggerSet LoggerSet{..} = do
fd <- readIORef lgrsetFdRef
when (isFDValid fd) $ do
case lgrsetLogger of
SL sl -> stopLoggers sl
ML ml -> stopLoggers ml
when (isJust lgrsetFilePath) $ closeFD fd
writeIORef lgrsetFdRef invalidFD
You can check if rmLoggerSet
is called by putting putStrLn
in cleanupAppResources
.
I'm debugging a problem with our
DevelMain
style approach to running a Yesod webserver in GHCi. When we're loaded inghciwatch
, we want to send logs to a file due to the way thatghciwatch
handlesstdout
.The code we use for that is here:
The
DevelMain
usesforeign-store
, following this pattern. The primary difference is that we use a continuation passing style for ourApp
, so it looks more like this:getApplicationRepl
calls`action site port app
finallycleanupAppResources site
When I call
DevelMain.update
for the first time, everything works. When I call it a second time, it sees the existingThreadId
and sends akillThread
to it. This should cause all thebracket
andfinally
to roll back and clean things up, includingrmLoggerSet
on the app's logger. This should unlock the file. Unfortunately, that does not happen - when we call intogetApplicationRepl
to start another webapp with the loaded logs, it fails with an error:resource busy (file is locked)
.If I mimic this in
ghci
without threading, it works fine.So something fishy is going on here.
I'll comment further with a reproduction or a diagnosis when I have one.