@@ -80,7 +80,7 @@ import Control.Monad.Error (ErrorT(..), runErrorT)
8080import Control.Exception ( IOException
8181 , SomeException
8282 , handle
83− , throw
83+ , throwIO
8484 , try
8585 , bracketOnError
8686 , mask
@@ -475,6 +475,10 @@ apiClose (ourEndPoint, theirEndPoint) connId connAlive = void . tryIO $ do
475475-- GUARANTEE: The state of the remote endpoint will not be changed.
476476apiSend :: EndPointPair -> ConnectionId -> IORef Bool -> [ByteString] -> IO (Either (TransportError SendErrorCode) ())
477477apiSend (ourEndPoint, theirEndPoint) connId connAlive payload =
478+ -- The 'join' joins the inner exception that we explicitly return) for
479+ -- instance if the connection is closed) with the outer exception (which is
480+ -- returned by 'try' when an exception is thrown by 'sendOn', and handled
481+ -- by 'withRemoteState')
478482 join <$> (try . mapExceptionIO sendFailed $ withRemoteState (ourEndPoint, theirEndPoint)
479483 -- RemoteEndPointInvalid
480484 (\_ -> fail "apiSend RELY violation")
@@ -636,7 +640,7 @@ createLocalEndPoint transport = do
636640 }
637641 return (TransportValid . (localEndPointAt addr ^= Just localEndPoint) . (nextEndPointId ^= ix + 1) $ vst, localEndPoint)
638642 TransportClosed ->
639− throw (TransportError NewEndPointFailed "Transport closed")
643+ throwIO (TransportError NewEndPointFailed "Transport closed")
640644
641645-- | Request a connection to a remote endpoint
642646--
@@ -676,7 +680,7 @@ requestConnectionTo ourEndPoint theirAddress = go
676680 -- won't matter.
677681 case endPointStateSnapshot of
678682 RemoteEndPointInvalid err ->
679− throw err
683+ throwIO err
680684
681685 RemoteEndPointClosing resolved _ ->
682686 -- If the remote endpoint is closing, then we need to block until
@@ -700,7 +704,7 @@ requestConnectionTo ourEndPoint theirAddress = go
700704 reply <- mapExceptionIO connectFailed $ doRemoteRequest (ourEndPoint, theirEndPoint) RequestConnectionId
701705 case decodeInt32 . BS.concat $ reply of
702706 Nothing ->
703− throw (connectFailed $ userError "Invalid integer")
707+ throwIO (connectFailed $ userError "Invalid integer")
704708 Just cid ->
705709 return (theirEndPoint, cid)
706710
@@ -712,7 +716,7 @@ requestConnectionTo ourEndPoint theirAddress = go
712716 findTheirEndPoint = do
713717 (theirEndPoint, isNew) <- modifyMVar ourState $ \st -> case st of
714718 LocalEndPointClosed ->
715− throw (TransportError ConnectFailed "Local endpoint closed")
719+ throwIO (TransportError ConnectFailed "Local endpoint closed")
716720 LocalEndPointValid vst ->
717721 case vst ^. localConnectionTo theirAddress of
718722 Just theirEndPoint ->
@@ -809,7 +813,7 @@ socketToEndPoint :: EndPointAddress -- ^ Our address
809813 -> IO (Either (TransportError ConnectErrorCode) (N.Socket, ConnectionRequestResponse))
810814socketToEndPoint (EndPointAddress ourAddress) theirAddress = try $ do
811815 (host, port, theirEndPointId) <- case decodeEndPointAddress theirAddress of
812− Nothing -> throw (failed . userError $ "Could not parse")
816+ Nothing -> throwIO (failed . userError $ "Could not parse")
813817 Just dec -> return dec
814818 addr:_ <- mapExceptionIO invalidAddress $ N.getAddrInfo Nothing (Just host) (Just port)
815819 bracketOnError (createSocket addr) N.sClose $ \sock -> do
@@ -819,7 +823,7 @@ socketToEndPoint (EndPointAddress ourAddress) theirAddress = try $ do
819823 sendMany sock (encodeInt32 theirEndPointId : prependLength [ourAddress])
820824 recvInt32 sock
821825 case tryToEnum response of
822− Nothing -> throw (failed . userError $ "Unexpected response")
826+ Nothing -> throwIO (failed . userError $ "Unexpected response")
823827 Just r -> return (sock, r)
824828 where
825829 createSocket :: N.AddrInfo -> IO N.Socket
@@ -892,7 +896,7 @@ doRemoteRequest (ourEndPoint, theirEndPoint) header = do
892896 let reqId = vst ^. nextCtrlRequestId
893897 return (LocalEndPointValid . (nextCtrlRequestId ^: (+ 1)) . (pendingCtrlRequestsAt reqId ^= Just reply) $ vst, reqId)
894898 LocalEndPointClosed ->
895− throw (userError "Local endpoint closed")
899+ throwIO (userError "Local endpoint closed")
896900 withRemoteState (ourEndPoint, theirEndPoint)
897901 -- RemoteEndPointInvalid
898902 (\_ -> fail "doRemoteRequest RELY violation")
@@ -901,7 +905,7 @@ doRemoteRequest (ourEndPoint, theirEndPoint) header = do
901905 -- RemoteEndPointClosing
902906 (\_ -> fail "doRemoteRequest RELY violation")
903907 -- RemoteEndPointClosed
904− (throw (userError "Remote endpoint closed"))
908+ (throwIO (userError "Remote endpoint closed"))
905909 takeMVar reply
906910
907911-- | Check if the remote endpoint is unused, and if so, send a CloseSocket request
@@ -1012,7 +1016,7 @@ modifyRemoteState (ourEndPoint, theirEndPoint) caseInvalid caseValid caseClosing
10121016 let err = TransportError (EventConnectionLost (remoteAddress theirEndPoint) incoming) (show ex)
10131017 writeChan (localChannel ourEndPoint) $ ErrorEvent err
10141018 -- .. and finally rethrow the exception
1015− throw ex
1019+ throwIO ex
10161020
10171021 -- Returns the set of incoming connections if we closed the connection, or
10181022 -- 'Nothing' if the endpoint was already closed