@@ -76,7 +76,6 @@ import Control.Distributed.Process.Internal.StrictMVar
76 , newEmptyMVar
76 , newEmptyMVar
78 , takeMVar
78 , takeMVar
81import Control.Concurrent.Chan (newChan, writeChan, readChan)
80import Control.Concurrent.Chan (newChan, writeChan, readChan)
82import qualified Control.Concurrent.MVar as MVar (newEmptyMVar, takeMVar)
81import qualified Control.Concurrent.MVar as MVar (newEmptyMVar, takeMVar)
@@ -119,6 +118,9 @@ import Control.Distributed.Process.Internal.Types
119 , LocalNode(..)
118 , LocalNode(..)
120 , MxEventBus(..)
119 , MxEventBus(..)
121 , LocalNodeState(..)
120 , LocalNodeState(..)
121+ , ValidLocalNodeState(..)
122+ , withValidLocalState
123+ , modifyValidLocalState_
122 , LocalProcess(..)
124 , LocalProcess(..)
123 , LocalProcessState(..)
125 , LocalProcessState(..)
124 , Process(..)
126 , Process(..)
@@ -231,7 +233,7 @@ newLocalNode transport rtable = do
231createBareLocalNode :: NT.EndPoint -> RemoteTable -> IO LocalNode
233createBareLocalNode :: NT.EndPoint -> RemoteTable -> IO LocalNode
232createBareLocalNode endPoint rtable = do
234createBareLocalNode endPoint rtable = do
233 unq <- randomIO
235 unq <- randomIO
234− state <- newMVar LocalNodeState
236+ state <- newMVar $ LocalNodeValid $ ValidLocalNodeState
235 { _localProcesses = Map.empty
237 { _localProcesses = Map.empty
236 , _localPidCounter = firstNonReservedProcessId
238 , _localPidCounter = firstNonReservedProcessId
237 , _localPidUnique = unq
239 , _localPidUnique = unq
@@ -322,7 +324,8 @@ startServiceProcesses node = do
323-- TODO: for now we just close the associated endpoint
325-- TODO: for now we just close the associated endpoint
324closeLocalNode :: LocalNode -> IO ()
326closeLocalNode :: LocalNode -> IO ()
325−closeLocalNode node =
327+closeLocalNode node = do
328+ modifyMVar_ (localState node) $ const $ return LocalNodeClosed
326 -- TODO: close all our processes, surely!?
329 -- TODO: close all our processes, surely!?
327 NT.closeEndPoint (localEndPoint node)
330 NT.closeEndPoint (localEndPoint node)
@@ -342,9 +345,9 @@ forkProcess node proc =
342 modifyMVarMasked (localState node) startProcess
345 modifyMVarMasked (localState node) startProcess
344 startProcess :: LocalNodeState -> IO (LocalNodeState, ProcessId)
347 startProcess :: LocalNodeState -> IO (LocalNodeState, ProcessId)
345− startProcess st = do
348+ startProcess (LocalNodeValid vst) = do
346− let lpid = LocalProcessId { lpidCounter = st ^. localPidCounter
349+ let lpid = LocalProcessId { lpidCounter = vst ^. localPidCounter
347− , lpidUnique = st ^. localPidUnique
350+ , lpidUnique = vst ^. localPidUnique
349 let pid = ProcessId { processNodeId = localNodeId node
352 let pid = ProcessId { processNodeId = localNodeId node
350 , processLocalId = lpid
353 , processLocalId = lpid
@@ -376,7 +379,7 @@ forkProcess node proc =
376 (return . DiedException . (show :: SomeException -> String)))]
379 (return . DiedException . (show :: SomeException -> String)))]
378 -- [Unified: Table 4, rules termination and exiting]
381 -- [Unified: Table 4, rules termination and exiting]
379− modifyMVar_ (localState node) (cleanupProcess pid)
382+ modifyValidLocalState_ (localState node) (cleanupProcess pid)
380 writeChan (localCtrlChan node) NCMsg
383 writeChan (localCtrlChan node) NCMsg
381 { ctrlMsgSender = ProcessIdentifier pid
384 { ctrlMsgSender = ProcessIdentifier pid
382 , ctrlMsgSignal = Died (ProcessIdentifier pid) reason
385 , ctrlMsgSignal = Died (ProcessIdentifier pid) reason
@@ -391,27 +394,30 @@ forkProcess node proc =
391 -- TODO: this doesn't look right at all - how do we know
394 -- TODO: this doesn't look right at all - how do we know
392 -- that newUnique represents a process id that is available!?
395 -- that newUnique represents a process id that is available!?
393 newUnique <- randomIO
396 newUnique <- randomIO
397+ return ( LocalNodeValid
394− return ( (localProcessWithId lpid ^= Just lproc)
398+ $ (localProcessWithId lpid ^= Just lproc)
395 . (localPidCounter ^= firstNonReservedProcessId)
399 . (localPidCounter ^= firstNonReservedProcessId)
396 . (localPidUnique ^= newUnique)
400 . (localPidUnique ^= newUnique)
405+ return ( LocalNodeValid
401− return ( (localProcessWithId lpid ^= Just lproc)
406+ $ (localProcessWithId lpid ^= Just lproc)
402 . (localPidCounter ^: (+ 1))
407 . (localPidCounter ^: (+ 1))
411+ startProcess LocalNodeClosed = throwIO $ userError "LocalNode closed"
407− cleanupProcess :: ProcessId -> LocalNodeState -> IO LocalNodeState
413+ cleanupProcess :: ProcessId -> ValidLocalNodeState -> IO ValidLocalNodeState
408− cleanupProcess pid st = do
414+ cleanupProcess pid vst = do
409 let pid' = ProcessIdentifier pid
415 let pid' = ProcessIdentifier pid
410− let (affected, unaffected) = Map.partitionWithKey (\(fr, _to) !_v -> impliesDeathOf pid' fr) (st ^. localConnections)
416+ let (affected, unaffected) = Map.partitionWithKey (\(fr, _to) !_v -> impliesDeathOf pid' fr) (vst ^. localConnections)
411 mapM_ (NT.close . fst) (Map.elems affected)
417 mapM_ (NT.close . fst) (Map.elems affected)
412 return $ (localProcessWithId (processLocalId pid) ^= Nothing)
418 return $ (localProcessWithId (processLocalId pid) ^= Nothing)
413 . (localConnections ^= unaffected)
419 . (localConnections ^= unaffected)
416-- note [tracer/forkProcess races]
422-- note [tracer/forkProcess races]
@@ -500,7 +506,7 @@ handleIncomingMessages node = go initConnectionState
500 case decode (BSL.fromChunks payload) of
506 case decode (BSL.fromChunks payload) of
501 ProcessIdentifier pid -> do
507 ProcessIdentifier pid -> do
502 let lpid = processLocalId pid
508 let lpid = processLocalId pid
503− mProc <- withMVar state $ return . (^. localProcessWithId lpid)
509+ mProc <- withValidLocalState state $ return . (^. localProcessWithId lpid)
504 case mProc of
510 case mProc of
505 Just proc ->
511 Just proc ->
506 go (incomingAt cid ^= Just (src, ToProc pid (processWeakQ proc)) $ st)
512 go (incomingAt cid ^= Just (src, ToProc pid (processWeakQ proc)) $ st)
@@ -509,7 +515,7 @@ handleIncomingMessages node = go initConnectionState
509 SendPortIdentifier chId -> do
515 SendPortIdentifier chId -> do
510 let lcid = sendPortLocalId chId
516 let lcid = sendPortLocalId chId
511 lpid = processLocalId (sendPortProcessId chId)
517 lpid = processLocalId (sendPortProcessId chId)
512− mProc <- withMVar state $ return . (^. localProcessWithId lpid)
518+ mProc <- withValidLocalState state $ return . (^. localProcessWithId lpid)
513 case mProc of
519 case mProc of
514 Just proc -> do
520 Just proc -> do
515 mChannel <- withMVar (processState proc) $ return . (^. typedChannelWithId lcid)
521 mChannel <- withMVar (processState proc) $ return . (^. typedChannelWithId lcid)
@@ -970,8 +976,8 @@ ncEffectGetInfo from pid =
970 them = (ProcessIdentifier pid)
976 them = (ProcessIdentifier pid)
972 node <- ask
978 node <- ask
973− mProc <- liftIO $
979+ mProc <- liftIO $ withValidLocalState (localState node)
974− withMVar (localState node) $ return . (^. localProcessWithId lpid)
980+ $ return . (^. localProcessWithId lpid)
975 case mProc of
981 case mProc of
976 Nothing -> dispatch (isLocal node (ProcessIdentifier from))
982 Nothing -> dispatch (isLocal node (ProcessIdentifier from))
977 from node (ProcessInfoNone DiedUnknownId)
983 from node (ProcessInfoNone DiedUnknownId)
@@ -1014,17 +1020,17 @@ ncEffectGetNodeStats :: ProcessId -> NodeId -> NC ()
1014ncEffectGetNodeStats from _nid = do
1020ncEffectGetNodeStats from _nid = do
1015 node <- ask
1021 node <- ask
1016 ncState <- StateT.get
1022 ncState <- StateT.get
1017− nodeState <- liftIO $ readMVar (localState node)
1023+ nodeState <- liftIO $ withValidLocalState (localState node) return
1018− let localProcesses' = nodeState ^. localProcesses
1019− stats =
1024+ let stats =
1020 NodeStats {
1025 NodeStats {
1021 nodeStatsNode = localNodeId node
1026 nodeStatsNode = localNodeId node
1022 , nodeStatsRegisteredNames = Map.size $ ncState ^. registeredHere
1027 , nodeStatsRegisteredNames = Map.size $ ncState ^. registeredHere
1023 , nodeStatsMonitors = Map.size $ ncState ^. monitors
1028 , nodeStatsMonitors = Map.size $ ncState ^. monitors
1024 , nodeStatsLinks = Map.size $ ncState ^. links
1029 , nodeStatsLinks = Map.size $ ncState ^. links
1025− , nodeStatsProcesses = Map.size localProcesses'
1030+ , nodeStatsProcesses = Map.size (nodeState ^. localProcesses)
1027 postAsMessage from stats
1032 postAsMessage from stats
1028--------------------------------------------------------------------------------
1034--------------------------------------------------------------------------------
1029-- Auxiliary --
1035-- Auxiliary --
1030--------------------------------------------------------------------------------
1036--------------------------------------------------------------------------------
@@ -1097,7 +1103,7 @@ unClosure closure = do
1097isValidLocalIdentifier :: Identifier -> NC Bool
1103isValidLocalIdentifier :: Identifier -> NC Bool
1098isValidLocalIdentifier ident = do
1104isValidLocalIdentifier ident = do
1099 node <- ask
1105 node <- ask
1100− liftIO . withMVar (localState node) $ \nSt ->
1106+ liftIO . withValidLocalState (localState node) $ \nSt ->
1101 case ident of
1107 case ident of
1102 NodeIdentifier nid ->
1108 NodeIdentifier nid ->
1103 return $ nid == localNodeId node
1109 return $ nid == localNodeId node
@@ -1135,8 +1141,8 @@ withLocalProc node pid p =
1135 -- By [Unified: table 6, rule missing_process] messages to dead processes
1141 -- By [Unified: table 6, rule missing_process] messages to dead processes
1136 -- can silently be dropped
1142 -- can silently be dropped
1137 let lpid = processLocalId pid in do
1143 let lpid = processLocalId pid in do
1144+ withValidLocalState (localState node) $ \vst ->
1138− mProc <- withMVar (localState node) $ return . (^. localProcessWithId lpid)
1145+ forM_ (vst ^. localProcessWithId lpid) p
1141--------------------------------------------------------------------------------
1147--------------------------------------------------------------------------------
1142-- Accessors --
1148-- Accessors --