ocharles/logging-effect

Manual blocking flush support

Closed this issue · 8 comments

I have a sigINT handler which writes a short message when invoked, however the main thread gracefully exits before the async withFDHandler can flush, causing me to lose some messages. Would it be possible to add a function I can call which would manually flush the buffer in a blocking manner?

Rather than that, I'd rather things "just worked". I'll see if I can get withFDHandler to flush on termination.

Hrm, https://github.com/ocharles/logging-effect/blob/master/src/Control/Monad/Log.hs#L476 should be taking care of that actually. Are you able to put together a minimal example?

{-# LANGUAGE OverloadedStrings #-}
module Example where

import Control.Concurrent
import Control.Concurrent.MVar
import Control.Monad
import Control.Monad.IO.Class
import Control.Monad.Log
import Control.Monad.Catch
import System.IO
import System.Posix.Signals
import qualified Text.PrettyPrint.Leijen.Text as PP

sigIntHandler :: LoggingT (WithSeverity PP.Doc) IO ()
              -> IO ()
sigIntHandler closeGracefully = runLogging $ do
  logNotice "received SIGINT, shutting down gracefully"
  closeGracefully

runLogging :: (Monad m, MonadIO m, MonadMask m)
           => LoggingT (WithSeverity PP.Doc) m a
           -> m a
runLogging app = withFDHandler defaultBatchingOptions stdout 0.4 80 $ \handler ->
  runLoggingT app (handler . renderWithSeverity id)

main :: IO ()
main = do
  putStrLn "start"
  interruptVar <- newEmptyMVar
  let closeGracefully = liftIO $ putMVar interruptVar ()
  void $ installHandler sigINT (Catch (sigIntHandler closeGracefully)) Nothing
  void . takeMVar $ interruptVar
  --threadDelay 1500000 -- uncommenting this leads to expected results
  putStrLn "end"

Without threadDelay:

➜  example stack --resolver lts-9.5 script example.hs
Using resolver: lts-9.5 specified on command line
start
^C[Notice] reecnedi
ved SIGINT, shutting down grace%

With threadDelay:

➜  example stack --resolver lts-9.5 script example.hs
Using resolver: lts-9.5 specified on command line
start
^C[Notice] received SIGINT, shutting down gracefully
end

Thank you! I'll try and get to this soon.

After digging in further, I discovered that the code example above opens the log handle (stdout) in the signal handler. If I restructure the code such that withFDHandler only gets called once in the main thread, and I pass handler around, I get expected results.

That was one of my initial thoughts, but I wondered if there were any other ways. But I think that is probably the way to do it, if you're happy threading the Handler. After all, those handlers only have IO, so I don't think there's much else that can be done. It looks like it does flush in the handler too, it just gets interleaved with mains stdout. If you log to a file it should all work as intended (just don't open the same file twice).

I'm happy with threading the Handler, sorry for the noise.

No noise, it was still a good discussion 😄