Make sure that terminal connections are closed properly on disconnects.

This commit is contained in:
Benjamin Summers 2019-12-19 05:16:52 -08:00
parent 8aa15e3b5c
commit e0bf6943c9
2 changed files with 23 additions and 12 deletions

View File

@ -113,8 +113,15 @@ serveTerminal env api word =
inp <- io $ newTBMChanIO 5
out <- io $ newTBMChanIO 5
atomically $ sp $ NounServ.mkConn inp out
runRIO env $
NounServ.wsConn "NOUNSERV (wsServ) " inp out wsc
let doit = runRIO env
$ NounServ.wsConn "NOUNSERV (wsServ) " inp out wsc
-- If `wai` kills this thread for any reason, the TBMChans
-- *need* to be closed. If they are not closed, the
-- terminal will not know that they disconnected.
finally doit $ atomically $ do
closeTBMChan inp
closeTBMChan out
data BadShip = BadShip Text
deriving (Show, Exception)

View File

@ -40,17 +40,20 @@ data Server i o a = Server
--------------------------------------------------------------------------------
withRIOThread RIO e a RIO e (Async a)
withRIOThread act = do
env <- ask
io $ async $ runRIO env $ act
wsConn :: (FromNoun i, ToNoun o, Show i, Show o, HasLogFunc e)
=> Utf8Builder
-> TBMChan i -> TBMChan o
-> WS.Connection
-> RIO e ()
wsConn pre inp out wsc = do
env <- ask
logWarn (pre <> "(wcConn) Connected!")
writer <- io $ async $ runRIO env $ forever $ do
writer <- withRIOThread $ forever $ do
logWarn (pre <> "(wsConn) Waiting for data.")
byt <- io $ toStrict <$> WS.receiveData wsc
logWarn (pre <> "Got data")
@ -58,7 +61,7 @@ wsConn pre inp out wsc = do
logWarn (pre <> "(wsConn) Decoded data, writing to chan")
atomically $ writeTBMChan inp dat
reader <- io $ async $ runRIO env $ forever $ do
reader <- withRIOThread $ forever $ do
logWarn (pre <> "Waiting for data from chan")
atomically (readTBMChan out) >>= \case
Nothing -> do
@ -68,15 +71,16 @@ wsConn pre inp out wsc = do
logWarn (pre <> "(wsConn) Got message! " <> displayShow msg)
io $ WS.sendBinaryData wsc $ fromStrict $ jamBS $ toNoun msg
res <- atomically (waitCatchSTM writer <|> waitCatchSTM reader)
logWarn $ displayShow (res :: Either SomeException ())
let cleanup = do
atomically (closeTBMChan inp >> closeTBMChan out)
cancel writer
cancel reader
flip finally cleanup $ do
res <- atomically (waitCatchSTM writer <|> waitCatchSTM reader)
logWarn $ displayShow (res :: Either SomeException ())
--------------------------------------------------------------------------------
wsClient :: i o e. (ToNoun o, FromNoun i, Show o, Show i, HasLogFunc e)