@@ -100,6 +100,7 @@ module Simplex.Messaging.Client
100100where
101101
102102import Control.Applicative ((<|>) )
103+ import Control.Concurrent (ThreadId , forkFinally , killThread , mkWeakThreadId )
103104import Control.Concurrent.Async
104105import Control.Concurrent.STM
105106import Control.Exception
@@ -138,13 +139,14 @@ import Simplex.Messaging.Transport.KeepAlive
138139import Simplex.Messaging.Transport.WebSockets (WS )
139140import Simplex.Messaging.Util (bshow , diffToMicroseconds , ifM , liftEitherWith , raceAny_ , threadDelay' , tshow , whenM )
140141import Simplex.Messaging.Version
142+ import System.Mem.Weak (Weak , deRefWeak )
141143import System.Timeout (timeout )
142144
143145-- | 'SMPClient' is a handle used to send commands to a specific SMP server.
144146--
145147-- Use 'getSMPClient' to connect to an SMP server and create a client handle.
146148data ProtocolClient v err msg = ProtocolClient
147- { action :: Maybe (Async () ),
149+ { action :: Maybe (Weak ThreadId ),
148150 thParams :: THandleParams v 'TClient,
149151 sessionTs :: UTCTime ,
150152 client_ :: PClient v err msg
@@ -475,15 +477,14 @@ getProtocolClient g transportSession@(_, srv, _) cfg@ProtocolClientConfig {qSize
475477 cVar <- newEmptyTMVarIO
476478 let tcConfig = (transportClientConfig networkConfig useHost) {alpn = clientALPN}
477479 username = proxyUsername transportSession
478- action <-
479- async $
480- runTransportClient tcConfig (Just username) useHost port' (Just $ keyHash srv) (client t c cVar)
481- `finally` atomically (tryPutTMVar cVar $ Left PCENetworkError )
480+ tId <-
481+ runTransportClient tcConfig (Just username) useHost port' (Just $ keyHash srv) (client t c cVar)
482+ `forkFinally` \ _ -> void (atomically . tryPutTMVar cVar $ Left PCENetworkError )
482483 c_ <- tcpConnectTimeout `timeout` atomically (takeTMVar cVar)
483484 case c_ of
484- Just (Right c') -> pure $ Right c' {action = Just action }
485+ Just (Right c') -> mkWeakThreadId tId >>= \ tId' -> pure $ Right c' {action = Just tId' }
485486 Just (Left e) -> pure $ Left e
486- Nothing -> cancel action $> Left PCENetworkError
487+ Nothing -> killThread tId $> Left PCENetworkError
487488
488489 useTransport :: (ServiceName , ATransport )
489490 useTransport = case port srv of
@@ -589,7 +590,7 @@ proxyUsername (userId, _, entityId_) = C.sha256Hash $ bshow userId <> maybe "" (
589590
590591-- | Disconnects client from the server and terminates client threads.
591592closeProtocolClient :: ProtocolClient v err msg -> IO ()
592- closeProtocolClient = mapM_ uninterruptibleCancel . action
593+ closeProtocolClient = mapM_ (deRefWeak >=> mapM_ killThread) . action
593594{-# INLINE closeProtocolClient #-}
594595
595596-- | SMP client error type.
0 commit comments