@@ -49,7 +49,13 @@ import Control.Monad.IO.Class (MonadIO, liftIO)
49import Control.Monad.State.Strict (MonadState, StateT, evalStateT, gets)
49import Control.Monad.State.Strict (MonadState, StateT, evalStateT, gets)
50import qualified Control.Monad.State.Strict as StateT (get, put)
50import qualified Control.Monad.State.Strict as StateT (get, put)
51import Control.Monad.Reader (MonadReader, ReaderT, runReaderT, ask)
51import Control.Monad.Reader (MonadReader, ReaderT, runReaderT, ask)
52−import Control.Exception (throwIO, SomeException, Exception, throwTo)
52+import Control.Exception
54+ , AsyncException(ThreadKilled)
53import qualified Control.Exception as Exception (catch)
59import qualified Control.Exception as Exception (catch)
54import Control.Concurrent (forkIO)
60import Control.Concurrent (forkIO)
55import Control.Distributed.Process.Internal.StrictMVar
61import Control.Distributed.Process.Internal.StrictMVar
@@ -193,25 +199,41 @@ newLocalNode transport rtable = do
193-- | Create a new local node (without any service processes running)
199-- | Create a new local node (without any service processes running)
194createBareLocalNode :: NT.EndPoint -> RemoteTable -> IO LocalNode
200createBareLocalNode :: NT.EndPoint -> RemoteTable -> IO LocalNode
195createBareLocalNode endPoint rtable = do
201createBareLocalNode endPoint rtable = do
196− unq <- randomIO
202+ unq <- randomIO
197− state <- newMVar LocalNodeState
203+ state <- newMVar LocalNodeState
198− { _localProcesses = Map.empty
204+ { _localProcesses = Map.empty
199− , _localPidCounter = firstNonReservedProcessId
205+ , _localPidCounter = firstNonReservedProcessId
200− , _localPidUnique = unq
206+ , _localPidUnique = unq
201− , _localConnections = Map.empty
207+ , _localConnections = Map.empty
203− ctrlChan <- newChan
209+ ctrlChan <- newChan
204− let node = LocalNode { localNodeId = NodeId $ NT.address endPoint
210+ let node = LocalNode { localNodeId = NodeId $ NT.address endPoint
205− , localEndPoint = endPoint
211+ , localEndPoint = endPoint
206− , localState = state
212+ , localState = state
207− , localCtrlChan = ctrlChan
213+ , localCtrlChan = ctrlChan
208− , localTracer = InactiveTracer
214+ , localTracer = InactiveTracer
209− , remoteTable = rtable
215+ , remoteTable = rtable
211− tracedNode <- startTracing node
217+ tracedNode <- startTracing node
219+ ncGo <- newEmptyMVar
220+ ncTid <- forkIO $ do
221+ tid <- takeMVar ncGo
212− void . forkIO $ runNodeController tracedNode
222+ (runNodeController tracedNode
223+ `Exception.catch` \(e :: SomeException) -> throwTo tid e)
225+ evTid <- forkIO $ do
213− void . forkIO $ handleIncomingMessages tracedNode
226+ (handleIncomingMessages tracedNode >> (stopNC node))
227+ `Exception.catch` \(e :: SomeException) -> throwTo ncTid e
214− return tracedNode
230+ return tracedNode
233+ writeChan (localCtrlChan node) NCMsg
234+ { ctrlMsgSender = NodeIdentifier (localNodeId node)
235+ , ctrlMsgSignal = SigShutdown
216-- | Start and register the service processes on a node
238-- | Start and register the service processes on a node
217-- (for now, this is only the logger)
239-- (for now, this is only the logger)
@@ -583,6 +605,8 @@ nodeController = do
583 ncEffectExit from to reason
605 ncEffectExit from to reason
584 NCMsg (ProcessIdentifier from) (GetInfo pid) ->
606 NCMsg (ProcessIdentifier from) (GetInfo pid) ->
585 ncEffectGetInfo from pid
607 ncEffectGetInfo from pid
608+ NCMsg _ SigShutdown ->
609+ liftIO $ throwIO ThreadKilled -- seems to make more sense than fail/error
586 unexpected ->
610 unexpected ->
587 error $ "nodeController: unexpected message " ++ show unexpected
611 error $ "nodeController: unexpected message " ++ show unexpected
@@ -902,6 +926,7 @@ destNid (Died _ _) = Nothing
902destNid (Kill pid _) = Just $ processNodeId pid
926destNid (Kill pid _) = Just $ processNodeId pid
903destNid (Exit pid _) = Just $ processNodeId pid
927destNid (Exit pid _) = Just $ processNodeId pid
904destNid (GetInfo pid) = Just $ processNodeId pid
928destNid (GetInfo pid) = Just $ processNodeId pid
929+destNid (SigShutdown) = Nothing
906-- | Check if a process is local to our own node
931-- | Check if a process is local to our own node
907isLocal :: LocalNode -> Identifier -> Bool
932isLocal :: LocalNode -> Identifier -> Bool