@@ -259,10 +259,10 @@ data ValidLocalEndPointState = ValidLocalEndPointState
259-- | /----------------\
259-- | /----------------\
262−-- \---> Valid ----+---> Closing
262+-- +---> Valid ----+---> Closing
265−-- \---> Closed
265+-- \---------------+---> Closed
267-- Init: There are two places where we create new remote endpoints: in
267-- Init: There are two places where we create new remote endpoints: in
268-- requestConnectionTo (in response to an API 'connect' call) and in
268-- requestConnectionTo (in response to an API 'connect' call) and in
@@ -565,16 +565,15 @@ apiCloseEndPoint transport evs ourEndPoint = do
565 case st of
565 case st of
566 RemoteEndPointInvalid _ ->
566 RemoteEndPointInvalid _ ->
567 return st
567 return st
568− RemoteEndPointInit _ ->
568+ RemoteEndPointInit resolved -> do
569− return st
569+ putMVar resolved ()
570+ return RemoteEndPointClosed
570 RemoteEndPointValid conn -> do
571 RemoteEndPointValid conn -> do
571− -- Try to send a CloseSocket request
572 tryIO $ sendOn conn [encodeInt32 CloseSocket]
572 tryIO $ sendOn conn [encodeInt32 CloseSocket]
573− -- .. but even if it fails, close the socket anyway
574 tryCloseSocket (remoteSocket conn)
573 tryCloseSocket (remoteSocket conn)
575 return RemoteEndPointClosed
574 return RemoteEndPointClosed
576− RemoteEndPointClosing _ conn -> do
575+ RemoteEndPointClosing resolved conn -> do
577− -- TODO: should we signal on resolved here?
576+ putMVar resolved ()
578 tryCloseSocket (remoteSocket conn)
577 tryCloseSocket (remoteSocket conn)
579 return RemoteEndPointClosed
578 return RemoteEndPointClosed
580 RemoteEndPointClosed ->
579 RemoteEndPointClosed ->
@@ -583,42 +582,44 @@ apiCloseEndPoint transport evs ourEndPoint = do
583-- | Special case of 'apiConnect': connect an endpoint to itself
582-- | Special case of 'apiConnect': connect an endpoint to itself
584connectToSelf :: LocalEndPoint
583connectToSelf :: LocalEndPoint
585 -> IO (Either (TransportError ConnectErrorCode) Connection)
584 -> IO (Either (TransportError ConnectErrorCode) Connection)
586−connectToSelf ourEndPoint = do
585+connectToSelf ourEndPoint = try . mapIOException connectFailed $ do
587− -- Here connAlive must an MVar because it is not protected by another lock
586+ connAlive <- newIORef True -- Protected by the local endpoint lock
588− connAlive <- newMVar True
589− mConnId <- tryIO (getNextConnectionId ourEndPoint)
587+ connId <- getNextConnectionId ourEndPoint
592− return . Left $ TransportError ConnectNotFound (show err)
594− writeChan ourChan $
588+ writeChan ourChan $
595− ConnectionOpened connId ReliableOrdered (localAddress ourEndPoint)
589+ ConnectionOpened connId ReliableOrdered (localAddress ourEndPoint)
596− return . Right $ Connection
590+ return Connection
597− { send = selfSend connAlive connId
591+ { send = selfSend connAlive connId
598− , close = selfClose connAlive connId
592+ , close = selfClose connAlive connId
601− ourChan :: Chan Event
602− ourChan = localChannel ourEndPoint
604− selfSend :: MVar Bool
595+ selfSend :: IORef Bool
605 -> ConnectionId
596 -> ConnectionId
606 -> [ByteString]
597 -> [ByteString]
607 -> IO (Either (TransportError SendErrorCode) ())
598 -> IO (Either (TransportError SendErrorCode) ())
608 selfSend connAlive connId msg =
599 selfSend connAlive connId msg =
609− modifyMVar connAlive $ \alive ->
600+ try . withMVar ourState $ \st -> case st of
601+ LocalEndPointValid _ -> do
602+ alive <- readIORef connAlive
610− if alive
603+ if alive
612− writeChan ourChan (Received connId msg)
604+ then writeChan ourChan (Received connId msg)
613− return (alive, Right ())
615− return (alive, Left (TransportError SendFailed "Connection closed"))
605+ else throwIO $ TransportError SendClosed "Connection closed"
606+ LocalEndPointClosed ->
607+ throwIO $ TransportError SendFailed "Endpoint closed"
617− selfClose :: MVar Bool -> ConnectionId -> IO ()
609+ selfClose :: IORef Bool -> ConnectionId -> IO ()
618 selfClose connAlive connId =
610 selfClose connAlive connId =
619− modifyMVar_ connAlive $ \alive -> do
611+ withMVar ourState $ \st -> case st of
612+ LocalEndPointValid _ -> do
613+ alive <- readIORef connAlive
620− when alive $ writeChan ourChan (ConnectionClosed connId)
615+ writeChan ourChan (ConnectionClosed connId)
621− return False
616+ writeIORef connAlive False
617+ LocalEndPointClosed ->
620+ ourChan = localChannel ourEndPoint
621+ ourState = localState ourEndPoint
622+ connectFailed = TransportError ConnectFailed . show
623--------------------------------------------------------------------------------
624--------------------------------------------------------------------------------
624-- Functions from TransportInternals --
625-- Functions from TransportInternals --