From 53b73bc905d268693731e1d5a4c996b00eebc89b Mon Sep 17 00:00:00 2001 From: Philipp Balzarek Date: Sat, 1 Jun 2013 17:51:59 +0200 Subject: [PATCH] allow read Worker to close streams on read failure and prevent it from stopping itself in this case --- source/Network/Xmpp/Concurrent/Threads.hs | 73 ++++++++++++++--------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/source/Network/Xmpp/Concurrent/Threads.hs b/source/Network/Xmpp/Concurrent/Threads.hs index 81b3867..11db1c6 100644 --- a/source/Network/Xmpp/Concurrent/Threads.hs +++ b/source/Network/Xmpp/Concurrent/Threads.hs @@ -23,37 +23,50 @@ import System.Log.Logger readWorker :: (Stanza -> IO ()) -> (XmppFailure -> IO ()) -> TMVar Stream - -> IO () -readWorker onStanza onConnectionClosed stateRef = Ex.mask_ go - where - go = do - res <- Ex.catches ( do - -- we don't know whether pull will - -- necessarily be interruptible - s <- atomically $ do + -> IO a +readWorker onStanza onConnectionClosed stateRef = forever . Ex.mask_ $ do + + s' <- Ex.catches ( do + -- we don't know whether pull will + -- necessarily be interruptible + atomically $ do s@(Stream con) <- readTMVar stateRef scs <- streamConnectionState <$> readTMVar con - when (scs == Closed) + when (stateIsClosed scs) retry - return s - allowInterrupt - Just <$> pullStanza s - ) - [ Ex.Handler $ \(Interrupt t) -> do - void $ handleInterrupts [t] - return Nothing - , Ex.Handler $ \(e :: XmppFailure) -> do - onConnectionClosed e - errorM "Pontarius.Xmpp" $ "Read error: " ++ show e - return Nothing - ] - case res of - Nothing -> go -- Caught an exception, nothing to do. TODO: Can this happen? - Just (Left e) -> do - infoM "Pontarius.Xmpp.Reader" $ - "Connection died: " ++ show e - onConnectionClosed e - Just (Right sta) -> onStanza sta >> go + return $ Just s + ) + [ Ex.Handler $ \(Interrupt t) -> do + void $ handleInterrupts [t] + return Nothing + + ] + case s' of + Nothing -> return () + Just s -> do + res <- Ex.catches (do + allowInterrupt + Just <$> pullStanza s + ) + [ Ex.Handler $ \(Interrupt t) -> do + void $ handleInterrupts [t] + return Nothing + , Ex.Handler $ \(e :: XmppFailure) -> do + errorM "Pontarius.Xmpp" $ "Read error: " + ++ show e + closeStreams s + onConnectionClosed e + return Nothing + ] + case res of + Nothing -> return () -- Caught an exception, nothing to + -- do. TODO: Can this happen? + Just (Left e) -> do + errorM "Pontarius.Xmpp" $ "Stanza error:" ++ show e + closeStreams s + onConnectionClosed e + Just (Right sta) -> void $ onStanza sta + where -- Defining an Control.Exception.allowInterrupt equivalent for GHC 7 -- compatibility. allowInterrupt :: IO () @@ -67,6 +80,10 @@ readWorker onStanza onConnectionClosed stateRef = Ex.mask_ go handleInterrupts ts = Ex.catch (atomically $ forM ts takeTMVar) (\(Interrupt t) -> handleInterrupts (t:ts)) + stateIsClosed Closed = True + stateIsClosed Finished = True + stateIsClosed _ = False + -- Two streams: input and output. Threads read from input stream and write to -- output stream.