@@ -84,6 +84,7 @@ import Control.Exception ( IOException
86 , onException
86 , onException
88import Data.IORef (IORef, newIORef, writeIORef, readIORef)
89import Data.IORef (IORef, newIORef, writeIORef, readIORef)
89import Data.ByteString (ByteString)
90import Data.ByteString (ByteString)
@@ -542,7 +543,7 @@ apiCloseEndPoint transport evs ourEndPoint = do
542 -- TODO: should we signal on resolved here?
543 -- TODO: should we signal on resolved here?
543 tryCloseSocket (remoteSocket conn)
544 tryCloseSocket (remoteSocket conn)
544 return RemoteEndPointClosed
545 return RemoteEndPointClosed
545− RemoteEndPointClosed ->
546+ RemoteEndPointClosed ->
546 return RemoteEndPointClosed
547 return RemoteEndPointClosed
548-- | Special case of 'apiConnect': connect an endpoint to itself
549-- | Special case of 'apiConnect': connect an endpoint to itself
@@ -1031,7 +1032,7 @@ remoteStateIdentity =
1031 , caseClosed = return RemoteEndPointClosed
1032 , caseClosed = return RemoteEndPointClosed
1034−-- | Like modifyMVar, but if an exception occurs don't restore the remote
1035+-- | Like modifyMVar, but if an I/O exception occurs don't restore the remote
1035-- endpoint to its original value but close it instead
1036-- endpoint to its original value but close it instead
1036modifyRemoteState :: EndPointPair
1037modifyRemoteState :: EndPointPair
1037 -> RemoteStatePatternMatch (RemoteState, a)
1038 -> RemoteStatePatternMatch (RemoteState, a)
@@ -1046,8 +1047,11 @@ modifyRemoteState (ourEndPoint, theirEndPoint) match =
1046 Right (st', a) -> do
1047 Right (st', a) -> do
1047 putMVar theirState st'
1048 putMVar theirState st'
1048 return a
1049 return a
1049− Left ex ->
1050+ Left ex -> do
1050− handleException ex vst
1051+ case fromException ex of
1052+ Just ioEx -> handleIOException ioEx vst
1053+ Nothing -> putMVar theirState st
1051 -- The other cases are less interesting, because unless the endpoint is
1055 -- The other cases are less interesting, because unless the endpoint is
1052 -- in Valid state we're not supposed to do any IO on it
1056 -- in Valid state we're not supposed to do any IO on it
1053 RemoteEndPointClosing resolved vst -> do
1057 RemoteEndPointClosing resolved vst -> do
@@ -1069,8 +1073,8 @@ modifyRemoteState (ourEndPoint, theirEndPoint) match =
1069 theirState :: MVar RemoteState
1073 theirState :: MVar RemoteState
1070 theirState = remoteState theirEndPoint
1074 theirState = remoteState theirEndPoint
1072− handleException :: SomeException -> ValidRemoteEndPointState -> IO a
1076+ handleIOException :: IOException -> ValidRemoteEndPointState -> IO ()
1073− handleException ex vst = do
1077+ handleIOException ex vst = do
1074 tryCloseSocket (remoteSocket vst)
1078 tryCloseSocket (remoteSocket vst)
1075 removeRemoteEndPoint (ourEndPoint, theirEndPoint)
1079 removeRemoteEndPoint (ourEndPoint, theirEndPoint)
1076 putMVar theirState RemoteEndPointClosed
1080 putMVar theirState RemoteEndPointClosed
@@ -1078,7 +1082,6 @@ modifyRemoteState (ourEndPoint, theirEndPoint) match =
1078 code = EventConnectionLost (remoteAddress theirEndPoint) incoming
1082 code = EventConnectionLost (remoteAddress theirEndPoint) incoming
1079 err = TransportError code (show ex)
1083 err = TransportError code (show ex)
1080 writeChan (localChannel ourEndPoint) $ ErrorEvent err
1084 writeChan (localChannel ourEndPoint) $ ErrorEvent err
1083-- | Like 'modifyRemoteState' but without a return value
1086-- | Like 'modifyRemoteState' but without a return value
1084modifyRemoteState_ :: EndPointPair
1087modifyRemoteState_ :: EndPointPair
@@ -1330,7 +1333,7 @@ handleIncomingMessages (ourEndPoint, theirEndPoint) = do
1331 -- Close the socket (if we don't have any outgoing connections)
1334 -- Close the socket (if we don't have any outgoing connections)
1332 closeSocket :: N.Socket -> IO Bool
1335 closeSocket :: N.Socket -> IO Bool
1333− closeSocket sock = do
1336+ closeSocket sock =
1334 modifyMVar theirState $ \st ->
1337 modifyMVar theirState $ \st ->
1335 case st of
1338 case st of
1336 RemoteEndPointInvalid _ ->
1339 RemoteEndPointInvalid _ ->