git.iko.soy/distributed-process
on master help sign in
Support monitor/link for nodes and ports
commit10ccea32736977ddd10ff3bb689116e85c41db93 authorEdsko de Vries <edsko@edsko.net> dateTue 3 Jul 2012, 17:10 (14 years ago) parentab7987d
7 files changed+444−199
distributed-process/src/Control/Distributed/Process.hs+25−8 distributed-process/src/Control/Distributed/Process/Internal/MessageT.hs+2−8 distributed-process/src/Control/Distributed/Process/Internal/Process/Primitives.hs+100−19 distributed-process/src/Control/Distributed/Process/Internal/Types.hs+107−46 distributed-process/src/Control/Distributed/Process/Node.hs+165−105 distributed-process/tests/TestCH.hs+42−10 distributed-process/tests/TestClosure.hs+3−3
distributed-process/src/Control/Distributed/Process.hs+25−8
@@ -18,6 +18,7 @@ module Control.Distributed.Process
1818 -- * Channels
1919 , ReceivePort
2020 , SendPort
21+ , sendPortId
2122 , newChan
2223 , sendChan
2324 , receiveChan
@@ -40,15 +41,23 @@ module Control.Distributed.Process
4041 , getSelfNode
4142 -- * Monitoring and linking
4243 , link
44+ , linkNode
45+ , linkPort
4346 , unlink
47+ , unlinkNode
48+ , unlinkPort
4449 , monitor
50+ , monitorNode
51+ , monitorPort
4552 , unmonitor
46− , LinkException(..)
53+ , ProcessLinkException(..)
54+ , NodeLinkException(..)
55+ , PortLinkException(..)
4756 , MonitorRef -- opaque
48− , MonitorNotification(..)
57+ , ProcessMonitorNotification(..)
58+ , NodeMonitorNotification(..)
59+ , PortMonitorNotification(..)
4960 , DiedReason(..)
50− , DidUnmonitor(..)
51− , DidUnlink(..)
5261 -- * Closures
5362 , Closure
5463 , Static
@@ -78,10 +87,12 @@ import Control.Distributed.Process.Internal.Types
7887 , Closure(..)
7988 , Static(..)
8089 , MonitorRef(..)
81− , MonitorNotification(..)
82− , LinkException(..)
83− , DidUnmonitor(..)
84− , DidUnlink(..)
90+ , ProcessMonitorNotification(..)
91+ , NodeMonitorNotification(..)
92+ , PortMonitorNotification(..)
93+ , ProcessLinkException(..)
94+ , NodeLinkException(..)
95+ , PortLinkException(..)
8596 , DiedReason(..)
8697 , SpawnRef(..)
8798 , DidSpawn(..)
@@ -122,8 +133,14 @@ import Control.Distributed.Process.Internal.Process.Primitives
122133 , getSelfNode
123134 -- Monitoring and linking
124135 , link
136+ , linkNode
137+ , linkPort
125138 , unlink
139+ , unlinkNode
140+ , unlinkPort
126141 , monitor
142+ , monitorNode
143+ , monitorPort
127144 , unmonitor
128145 -- Auxiliary API
129146 , catch
distributed-process/src/Control/Distributed/Process/Internal/MessageT.hs+2−8
@@ -27,9 +27,8 @@ import Control.Monad.IO.Class (MonadIO, liftIO)
2727import Control.Concurrent.Chan (writeChan)
2828import Control.Distributed.Process.Internal.Types
2929 ( Identifier(..)
30+ , nodeOf
3031 , NodeId(nodeAddress)
31− , ProcessId(processNodeId)
32− , ChannelId(channelProcessId)
3332 , LocalNode(localCtrlChan, localEndPoint)
3433 , NCMsg(NCMsg, ctrlMsgSender, ctrlMsgSignal)
3534 , DiedReason(DiedDisconnect)
@@ -122,7 +121,7 @@ setupConnTo :: MonadIO m => Identifier -> MessageT m (Maybe NT.Connection)
122121setupConnTo them = do
123122 endPoint <- localEndPoint `liftM` getLocalNode
124123 mConn <- liftIO $ NT.connect endPoint
125− (nodeAddress . identifierNode $ them)
124+ (nodeAddress . nodeOf $ them)
126125 NT.ReliableOrdered
127126 NT.defaultConnectHints
128127 case mConn of
@@ -144,11 +143,6 @@ connTo them = do
144143 Just conn -> return $ Just conn
145144 Nothing -> setupConnTo them
146145
147−identifierNode :: Identifier -> NodeId
148−identifierNode (NodeIdentifier nid) = nid
149−identifierNode (ProcessIdentifier pid) = processNodeId pid
150−identifierNode (ChannelIdentifier cid) = processNodeId (channelProcessId cid)
151−
152146--------------------------------------------------------------------------------
153147-- Accessors --
154148--------------------------------------------------------------------------------
distributed-process/src/Control/Distributed/Process/Internal/Process/Primitives.hs+100−19
@@ -36,6 +36,12 @@ module Control.Distributed.Process.Internal.Process.Primitives
3636 , spawnAsync
3737 , spawnLink
3838 , spawnMonitor
39+ , linkNode
40+ , linkPort
41+ , unlinkNode
42+ , unlinkPort
43+ , monitorNode
44+ , monitorPort
3945 ) where
4046
4147import Prelude hiding (catch)
@@ -82,9 +88,13 @@ import Control.Distributed.Process.Internal.Types
8288 , channelCounter
8389 , typedChannelWithId
8490 , TypedChannel(..)
85− , ChannelId(..)
91+ , SendPortId(..)
8692 , Identifier(..)
8793 , procMsg
94+ , DidUnmonitor(..)
95+ , DidUnlinkProcess(..)
96+ , DidUnlinkNode(..)
97+ , DidUnlinkPort(..)
8898 )
8999import Control.Distributed.Process.Internal.MessageT
90100 ( sendMessage
@@ -118,9 +128,9 @@ newChan = do
118128 liftIO . modifyMVar (processState proc) $ \st -> do
119129 chan <- liftIO . atomically $ newTChan
120130 let lcid = st ^. channelCounter
121− cid = ChannelId { channelProcessId = processId proc
122− , channelLocalId = lcid
123− }
131+ cid = SendPortId { sendPortProcessId = processId proc
132+ , sendPortLocalId = lcid
133+ }
124134 sport = SendPort cid
125135 rport = ReceivePortSingle chan
126136 tch = TypedChannel chan
@@ -132,7 +142,7 @@ newChan = do
132142
133143-- | Send a message on a typed channel
134144sendChan :: Serializable a => SendPort a -> a -> Process ()
135−sendChan (SendPort them) msg = procMsg $ sendBinary (ChannelIdentifier them) msg
145+sendChan (SendPort cid) msg = procMsg $ sendBinary (SendPortIdentifier cid) msg
136146
137147-- | Wait for a message on a typed channel
138148receiveChan :: Serializable a => ReceivePort a -> Process a
@@ -250,22 +260,43 @@ getSelfNode = localNodeId <$> procMsg getLocalNode
250260-- Linking makes no distinction between normal and abnormal termination of
251261-- the remote process.
252262link :: ProcessId -> Process ()
253−link = sendCtrlMsg Nothing . Link
254−
255−-- | Remove a link (asynchronous)
256−unlink :: ProcessId -> Process ()
257−unlink = sendCtrlMsg Nothing . Unlink
263+link = sendCtrlMsg Nothing . Link . ProcessIdentifier
258264
259265-- | Monitor another process (asynchronous)
260266monitor :: ProcessId -> Process MonitorRef
261−monitor them = do
262− monitorRef <- getMonitorRefFor them
263− sendCtrlMsg Nothing $ Monitor them monitorRef
264− return monitorRef
267+monitor = monitor' . ProcessIdentifier
265268
266−-- | Remove a monitor (asynchronous)
269+-- | Remove a link (synchronous)
270+unlink :: ProcessId -> Process ()
271+unlink pid = do
272+ unlinkAsync pid
273+ receiveWait [ matchIf (\(DidUnlinkProcess pid') -> pid' == pid)
274+ (\_ -> return ())
275+ ]
276+
277+-- | Remove a node link (synchronous)
278+unlinkNode :: NodeId -> Process ()
279+unlinkNode nid = do
280+ unlinkNodeAsync nid
281+ receiveWait [ matchIf (\(DidUnlinkNode nid') -> nid' == nid)
282+ (\_ -> return ())
283+ ]
284+
285+-- | Remove a channel (send port) link (synchronous)
286+unlinkPort :: SendPort a -> Process ()
287+unlinkPort sport = do
288+ unlinkPortAsync sport
289+ receiveWait [ matchIf (\(DidUnlinkPort cid) -> cid == sendPortId sport)
290+ (\_ -> return ())
291+ ]
292+
293+-- | Remove a monitor (synchronous)
267294unmonitor :: MonitorRef -> Process ()
268−unmonitor = sendCtrlMsg Nothing . Unmonitor
295+unmonitor ref = do
296+ unmonitorAsync ref
297+ receiveWait [ matchIf (\(DidUnmonitor ref') -> ref' == ref)
298+ (\_ -> return ())
299+ ]
269300
270301--------------------------------------------------------------------------------
271302-- Auxiliary API --
@@ -311,17 +342,56 @@ spawnMonitor nid proc = do
311342 ref <- monitor pid
312343 return (pid, ref)
313344
345+-- | Monitor a node
346+monitorNode :: NodeId -> Process MonitorRef
347+monitorNode =
348+ monitor' . NodeIdentifier
349+
350+-- | Monitor a typed channel
351+monitorPort :: forall a. Serializable a => SendPort a -> Process MonitorRef
352+monitorPort (SendPort cid) =
353+ monitor' (SendPortIdentifier cid)
354+
355+-- | Remove a monitor (asynchronous)
356+unmonitorAsync :: MonitorRef -> Process ()
357+unmonitorAsync =
358+ sendCtrlMsg Nothing . Unmonitor
359+
360+-- | Link to a node
361+linkNode :: NodeId -> Process ()
362+linkNode = link' . NodeIdentifier
363+
364+-- | Link to a channel (send port)
365+linkPort :: SendPort a -> Process ()
366+linkPort (SendPort cid) =
367+ link' (SendPortIdentifier cid)
368+
369+-- | Remove a process link (asynchronous)
370+unlinkAsync :: ProcessId -> Process ()
371+unlinkAsync =
372+ sendCtrlMsg Nothing . Unlink . ProcessIdentifier
373+
374+-- | Remove a node link (asynchronous)
375+unlinkNodeAsync :: NodeId -> Process ()
376+unlinkNodeAsync =
377+ sendCtrlMsg Nothing . Unlink . NodeIdentifier
378+
379+-- | Remove a channel (send port) link (asynchronous)
380+unlinkPortAsync :: SendPort a -> Process ()
381+unlinkPortAsync (SendPort cid) =
382+ sendCtrlMsg Nothing . Unlink $ SendPortIdentifier cid
383+
314384--------------------------------------------------------------------------------
315385-- Auxiliary functions --
316386--------------------------------------------------------------------------------
317387
318−getMonitorRefFor :: ProcessId -> Process MonitorRef
319−getMonitorRefFor pid = do
388+getMonitorRefFor :: Identifier -> Process MonitorRef
389+getMonitorRefFor ident = do
320390 proc <- ask
321391 liftIO $ modifyMVar (processState proc) $ \st -> do
322392 let counter = st ^. monitorCounter
323393 return ( monitorCounter ^: (+ 1) $ st
324− , MonitorRef pid counter
394+ , MonitorRef ident counter
325395 )
326396
327397getSpawnRef :: Process SpawnRef
@@ -333,6 +403,17 @@ getSpawnRef = do
333403 , SpawnRef counter
334404 )
335405
406+-- | Monitor a process/node/channel
407+monitor' :: Identifier -> Process MonitorRef
408+monitor' ident = do
409+ monitorRef <- getMonitorRefFor ident
410+ sendCtrlMsg Nothing $ Monitor monitorRef
411+ return monitorRef
412+
413+-- | Link to a process/node/channel
414+link' :: Identifier -> Process ()
415+link' = sendCtrlMsg Nothing . Link
416+
336417-- Send a control message
337418sendCtrlMsg :: Maybe NodeId -- ^ Nothing for the local node
338419 -> ProcessSignal -- ^ Message to send
distributed-process/src/Control/Distributed/Process/Internal/Types.hs+107−46
@@ -10,6 +10,7 @@ module Control.Distributed.Process.Internal.Types
1010 , LocalProcessId(..)
1111 , ProcessId(..)
1212 , Identifier(..)
13+ , nodeOf
1314 -- * Local nodes and processes
1415 , LocalNode(..)
1516 , LocalNodeState(..)
@@ -18,8 +19,8 @@ module Control.Distributed.Process.Internal.Types
1819 , Process(..)
1920 , procMsg
2021 -- * Typed channels
21− , LocalChannelId
22− , ChannelId(..)
22+ , LocalSendPortId
23+ , SendPortId(..)
2324 , TypedChannel(..)
2425 , SendPort(..)
2526 , ReceivePort(..)
@@ -34,11 +35,17 @@ module Control.Distributed.Process.Internal.Types
3435 , Message(..)
3536 -- * Node controller user-visible data types
3637 , MonitorRef(..)
37− , MonitorNotification(..)
38− , LinkException(..)
38+ , ProcessMonitorNotification(..)
39+ , NodeMonitorNotification(..)
40+ , PortMonitorNotification(..)
41+ , ProcessLinkException(..)
42+ , NodeLinkException(..)
43+ , PortLinkException(..)
3944 , DiedReason(..)
4045 , DidUnmonitor(..)
41− , DidUnlink(..)
46+ , DidUnlinkProcess(..)
47+ , DidUnlinkNode(..)
48+ , DidUnlinkPort(..)
4249 , SpawnRef(..)
4350 , DidSpawn(..)
4451 -- * Node controller internal data types
@@ -121,10 +128,20 @@ instance Show ProcessId where
121128
122129-- | Union of all kinds of identifiers
123130data Identifier =
124− ProcessIdentifier ProcessId
125− | NodeIdentifier NodeId
126− | ChannelIdentifier ChannelId
127− deriving (Show, Eq, Ord)
131+ NodeIdentifier NodeId
132+ | ProcessIdentifier ProcessId
133+ | SendPortIdentifier SendPortId
134+ deriving (Eq, Ord)
135+
136+instance Show Identifier where
137+ show (NodeIdentifier nid) = show nid
138+ show (ProcessIdentifier pid) = show pid
139+ show (SendPortIdentifier cid) = show cid
140+
141+nodeOf :: Identifier -> NodeId
142+nodeOf (NodeIdentifier nid) = nid
143+nodeOf (ProcessIdentifier pid) = processNodeId pid
144+nodeOf (SendPortIdentifier cid) = processNodeId (sendPortProcessId cid)
128145
129146--------------------------------------------------------------------------------
130147-- Local nodes and processes --
@@ -165,7 +182,7 @@ data LocalProcessState = LocalProcessState
165182 { _monitorCounter :: Int32
166183 , _spawnCounter :: Int32
167184 , _channelCounter :: Int32
168− , _typedChannels :: Map LocalChannelId TypedChannel
185+ , _typedChannels :: Map LocalSendPortId TypedChannel
169186 }
170187
171188-- | The Cloud Haskell 'Process' type
@@ -181,18 +198,22 @@ procMsg = Process . Trans.lift
181198-- Typed channels --
182199--------------------------------------------------------------------------------
183200
184−type LocalChannelId = Int32
201+type LocalSendPortId = Int32
185202
186−data ChannelId = ChannelId {
187− channelProcessId :: ProcessId
188− , channelLocalId :: LocalChannelId
203+data SendPortId = SendPortId {
204+ sendPortProcessId :: ProcessId
205+ , sendPortLocalId :: LocalSendPortId
189206 }
190− deriving (Show, Eq, Ord)
207+ deriving (Eq, Ord)
208+
209+instance Show SendPortId where
210+ show cid = show (sendPortProcessId cid) ++ ":" ++ show (sendPortLocalId cid)
191211
192212data TypedChannel = forall a. Serializable a => TypedChannel (TChan a)
193213
194214-- | The send send of a typed channel (serializable)
195−newtype SendPort a = SendPort ChannelId deriving (Typeable, Binary)
215+newtype SendPort a = SendPort { sendPortId :: SendPortId }
216+ deriving (Typeable, Binary, Show, Eq, Ord)
196217
197218-- | The receive end of a typed channel (not serializable)
198219data ReceivePort a =
@@ -274,22 +295,46 @@ data Message = Message
274295
275296-- | MonitorRef is opaque for regular Cloud Haskell processes
276297data MonitorRef = MonitorRef
277− { -- | PID of the process to be monitored (for routing purposes)
278− monitorRefPid :: ProcessId
298+ { -- | ID of the entity to be monitored
299+ monitorRefIdent :: Identifier
279300 -- | Unique to distinguish multiple monitor requests by the same process
280301 , monitorRefCounter :: Int32
281302 }
282303 deriving (Eq, Ord, Show)
283304
284−-- | Messages sent by monitors
285−data MonitorNotification = MonitorNotification MonitorRef ProcessId DiedReason
305+-- | Message sent by process monitors
306+data ProcessMonitorNotification =
307+ ProcessMonitorNotification MonitorRef ProcessId DiedReason
308+ deriving (Typeable, Show)
309+
310+-- | Message sent by node monitors
311+data NodeMonitorNotification =
312+ NodeMonitorNotification MonitorRef NodeId DiedReason
313+ deriving (Typeable, Show)
314+
315+-- | Message sent by channel (port) monitors
316+data PortMonitorNotification =
317+ PortMonitorNotification MonitorRef SendPortId DiedReason
286318 deriving (Typeable, Show)
287319
288320-- | Exceptions thrown when a linked process dies
289−data LinkException = LinkException ProcessId DiedReason
321+data ProcessLinkException =
322+ ProcessLinkException ProcessId DiedReason
290323 deriving (Typeable, Show)
291324
292−instance Exception LinkException
325+-- | Exception thrown when a linked node dies
326+data NodeLinkException =
327+ NodeLinkException NodeId DiedReason
328+ deriving (Typeable, Show)
329+
330+-- | Exception thrown when a linked channel (port) dies
331+data PortLinkException =
332+ PortLinkException SendPortId DiedReason
333+ deriving (Typeable, Show)
334+
335+instance Exception ProcessLinkException
336+instance Exception NodeLinkException
337+instance Exception PortLinkException
293338
294339-- | Why did a process die?
295340data DiedReason =
@@ -302,8 +347,8 @@ data DiedReason =
302347 | DiedDisconnect
303348 -- | The process node died
304349 | DiedNodeDown
305− -- | Invalid process ID
306− | DiedNoProc
350+ -- | Invalid (process/node/channel) identifier
351+ | DiedUnknownId
307352 deriving (Show, Eq)
308353
309354-- | (Asynchronous) reply from unmonitor
@@ -311,7 +356,15 @@ newtype DidUnmonitor = DidUnmonitor MonitorRef
311356 deriving (Typeable, Binary)
312357
313358-- | (Asynchronous) reply from unlink
314−newtype DidUnlink = DidUnlink ProcessId
359+newtype DidUnlinkProcess = DidUnlinkProcess ProcessId
360+ deriving (Typeable, Binary)
361+
362+-- | (Asynchronous) reply from unlinkNode
363+newtype DidUnlinkNode = DidUnlinkNode NodeId
364+ deriving (Typeable, Binary)
365+
366+-- | (Asynchronous) reply from unlinkPort
367+newtype DidUnlinkPort = DidUnlinkPort SendPortId
315368 deriving (Typeable, Binary)
316369
317370-- | 'SpawnRef' are used to return pids of spawned processes
@@ -335,9 +388,9 @@ data NCMsg = NCMsg
335388
336389-- | Signals to the node controller (see 'NCMsg')
337390data ProcessSignal =
338− Link ProcessId
339− | Unlink ProcessId
340− | Monitor ProcessId MonitorRef
391+ Link Identifier
392+ | Unlink Identifier
393+ | Monitor MonitorRef
341394 | Unmonitor MonitorRef
342395 | Died Identifier DiedReason
343396 | Spawn (Closure (Process ())) SpawnRef
@@ -355,22 +408,30 @@ instance Binary ProcessId where
355408 put pid = put (processNodeId pid) >> put (processLocalId pid)
356409 get = ProcessId <$> get <*> get
357410
358−instance Binary MonitorNotification where
359− put (MonitorNotification ref pid reason) = put ref >> put pid >> put reason
360− get = MonitorNotification <$> get <*> get <*> get
411+instance Binary ProcessMonitorNotification where
412+ put (ProcessMonitorNotification ref pid reason) = put ref >> put pid >> put reason
413+ get = ProcessMonitorNotification <$> get <*> get <*> get
414+
415+instance Binary NodeMonitorNotification where
416+ put (NodeMonitorNotification ref pid reason) = put ref >> put pid >> put reason
417+ get = NodeMonitorNotification <$> get <*> get <*> get
418+
419+instance Binary PortMonitorNotification where
420+ put (PortMonitorNotification ref pid reason) = put ref >> put pid >> put reason
421+ get = PortMonitorNotification <$> get <*> get <*> get
361422
362423instance Binary NCMsg where
363424 put msg = put (ctrlMsgSender msg) >> put (ctrlMsgSignal msg)
364425 get = NCMsg <$> get <*> get
365426
366427instance Binary MonitorRef where
367− put ref = put (monitorRefPid ref) >> put (monitorRefCounter ref)
428+ put ref = put (monitorRefIdent ref) >> put (monitorRefCounter ref)
368429 get = MonitorRef <$> get <*> get
369430
370431instance Binary ProcessSignal where
371432 put (Link pid) = putWord8 0 >> put pid
372433 put (Unlink pid) = putWord8 1 >> put pid
373− put (Monitor pid ref) = putWord8 2 >> put pid >> put ref
434+ put (Monitor ref) = putWord8 2 >> put ref
374435 put (Unmonitor ref) = putWord8 3 >> put ref
375436 put (Died who reason) = putWord8 4 >> put who >> put reason
376437 put (Spawn proc ref) = putWord8 5 >> put proc >> put ref
@@ -379,7 +440,7 @@ instance Binary ProcessSignal where
379440 case header of
380441 0 -> Link <$> get
381442 1 -> Unlink <$> get
382− 2 -> Monitor <$> get <*> get
443+ 2 -> Monitor <$> get
383444 3 -> Unmonitor <$> get
384445 4 -> Died <$> get <*> get
385446 5 -> Spawn <$> get <*> get
@@ -390,7 +451,7 @@ instance Binary DiedReason where
390451 put (DiedException e) = putWord8 1 >> put e
391452 put DiedDisconnect = putWord8 2
392453 put DiedNodeDown = putWord8 3
393− put DiedNoProc = putWord8 4
454+ put DiedUnknownId = putWord8 4
394455 get = do
395456 header <- getWord8
396457 case header of
@@ -398,7 +459,7 @@ instance Binary DiedReason where
398459 1 -> DiedException <$> get
399460 2 -> return DiedDisconnect
400461 3 -> return DiedNodeDown
401− 4 -> return DiedNoProc
462+ 4 -> return DiedUnknownId
402463 _ -> fail "DiedReason.get: invalid"
403464
404465instance Binary (Closure a) where
@@ -409,20 +470,20 @@ instance Binary DidSpawn where
409470 put (DidSpawn ref pid) = put ref >> put pid
410471 get = DidSpawn <$> get <*> get
411472
412−instance Binary ChannelId where
413− put cid = put (channelProcessId cid) >> put (channelLocalId cid)
414− get = ChannelId <$> get <*> get
473+instance Binary SendPortId where
474+ put cid = put (sendPortProcessId cid) >> put (sendPortLocalId cid)
475+ get = SendPortId <$> get <*> get
415476
416477instance Binary Identifier where
417− put (ProcessIdentifier pid) = putWord8 0 >> put pid
418− put (NodeIdentifier nid) = putWord8 1 >> put nid
419− put (ChannelIdentifier cid) = putWord8 2 >> put cid
478+ put (ProcessIdentifier pid) = putWord8 0 >> put pid
479+ put (NodeIdentifier nid) = putWord8 1 >> put nid
480+ put (SendPortIdentifier cid) = putWord8 2 >> put cid
420481 get = do
421482 header <- getWord8
422483 case header of
423484 0 -> ProcessIdentifier <$> get
424485 1 -> NodeIdentifier <$> get
425− 2 -> ChannelIdentifier <$> get
486+ 2 -> SendPortIdentifier <$> get
426487 _ -> fail "Identifier.get: invalid"
427488
428489instance Binary StaticLabel where
@@ -485,13 +546,13 @@ monitorCounter = accessor _monitorCounter (\cnt st -> st { _monitorCounter = cnt
485546spawnCounter :: Accessor LocalProcessState Int32
486547spawnCounter = accessor _spawnCounter (\cnt st -> st { _spawnCounter = cnt })
487548
488−channelCounter :: Accessor LocalProcessState LocalChannelId
549+channelCounter :: Accessor LocalProcessState LocalSendPortId
489550channelCounter = accessor _channelCounter (\cnt st -> st { _channelCounter = cnt })
490551
491−typedChannels :: Accessor LocalProcessState (Map LocalChannelId TypedChannel)
552+typedChannels :: Accessor LocalProcessState (Map LocalSendPortId TypedChannel)
492553typedChannels = accessor _typedChannels (\cs st -> st { _typedChannels = cs })
493554
494−typedChannelWithId :: LocalChannelId -> Accessor LocalProcessState (Maybe TypedChannel)
555+typedChannelWithId :: LocalSendPortId -> Accessor LocalProcessState (Maybe TypedChannel)
495556typedChannelWithId cid = typedChannels >>> DAC.mapMaybe cid
496557
497558remoteTableLabels :: Accessor RemoteTable (Map String Dynamic)
distributed-process/src/Control/Distributed/Process/Node.hs+165−105
@@ -13,7 +13,14 @@ import System.IO (fixIO)
1313import qualified Data.ByteString.Lazy as BSL (fromChunks)
1414import Data.Binary (decode)
1515import Data.Map (Map)
16−import qualified Data.Map as Map (empty, lookup, insert, delete, toList)
16+import qualified Data.Map as Map
17+ ( empty
18+ , lookup
19+ , insert
20+ , delete
21+ , toList
22+ , partitionWithKey
23+ )
1724import qualified Data.List as List (delete)
1825import Data.Set (Set)
1926import qualified Data.Set as Set (empty, insert, delete, member)
@@ -73,18 +80,26 @@ import Control.Distributed.Process.Internal.Types
7380 , localPidUnique
7481 , localProcessWithId
7582 , MonitorRef(..)
76− , MonitorNotification(..)
77− , LinkException(..)
83+ , ProcessMonitorNotification(..)
84+ , NodeMonitorNotification(..)
85+ , PortMonitorNotification(..)
86+ , ProcessLinkException(..)
87+ , NodeLinkException(..)
88+ , PortLinkException(..)
7889 , DidUnmonitor(..)
79− , DidUnlink(..)
90+ , DidUnlinkProcess(..)
91+ , DidUnlinkNode(..)
92+ , DidUnlinkPort(..)
8093 , SpawnRef
8194 , DidSpawn(..)
8295 , Closure(..)
8396 , Static(..)
97+ , Message
8498 , MessageT
8599 , TypedChannel(..)
86100 , Identifier(..)
87− , ChannelId(..)
101+ , nodeOf
102+ , SendPortId(..)
88103 , typedChannelWithId
89104 )
90105import Control.Distributed.Process.Serializable (Serializable)
@@ -249,9 +264,9 @@ handleIncomingMessages node = go [] Map.empty Map.empty Set.empty
249264 -- incoming connections (this requires a Transport layer
250265 -- extension). (**)
251266 go (List.delete cid uninitConns) procs chans ctrls
252− ChannelIdentifier chId -> do
253− let lcid = channelLocalId chId
254− lpid = processLocalId (channelProcessId chId)
267+ SendPortIdentifier chId -> do
268+ let lcid = sendPortLocalId chId
269+ lpid = processLocalId (sendPortProcessId chId)
255270 mProc <- withMVar state $ return . (^. localProcessWithId lpid)
256271 case mProc of
257272 Just proc -> do
@@ -325,9 +340,9 @@ runNodeController node =
325340
326341data NCState = NCState
327342 { -- Mapping from remote processes to linked local processes
328− _links :: Map NodeId (Map LocalProcessId (Set ProcessId))
343+ _links :: Map Identifier (Set ProcessId)
329344 -- Mapping from remote processes to monitoring local processes
330− , _monitors :: Map NodeId (Map LocalProcessId (Map ProcessId (Set MonitorRef)))
345+ , _monitors :: Map Identifier (Set (ProcessId, MonitorRef))
331346 }
332347
333348newtype NC a = NC { unNC :: StateT NCState (MessageT IO) a }
@@ -362,24 +377,22 @@ nodeController = do
362377 case msg of
363378 NCMsg (ProcessIdentifier from) (Link them) ->
364379 ncEffectMonitor from them Nothing
365− NCMsg (ProcessIdentifier from) (Monitor them ref) ->
366− ncEffectMonitor from them (Just ref)
380+ NCMsg (ProcessIdentifier from) (Monitor ref) ->
381+ ncEffectMonitor from (monitorRefIdent ref) (Just ref)
367382 NCMsg (ProcessIdentifier from) (Unlink them) ->
368383 ncEffectUnlink from them
369384 NCMsg (ProcessIdentifier from) (Unmonitor ref) ->
370385 ncEffectUnmonitor from ref
371− NCMsg _from (Died (NodeIdentifier nid) reason) ->
372− ncEffectNodeDied nid reason
373− NCMsg _from (Died (ProcessIdentifier pid) reason) ->
374− ncEffectProcessDied pid reason
386+ NCMsg _from (Died ident reason) ->
387+ ncEffectDied ident reason
375388 NCMsg (ProcessIdentifier from) (Spawn proc ref) ->
376389 ncEffectSpawn from proc ref
377390 unexpected ->
378− error $ "Unexpected message " ++ show unexpected
391+ error $ "nodeController: unexpected message " ++ show unexpected
379392
380393-- [Unified: Table 10]
381394ncEffectMonitor :: ProcessId -- ^ Who's watching?
382− -> ProcessId -- ^ Who's being watched?
395+ -> Identifier -- ^ Who's being watched?
383396 -> Maybe MonitorRef -- ^ 'Nothing' to link
384397 -> NC ()
385398ncEffectMonitor from them mRef = do
@@ -387,73 +400,62 @@ ncEffectMonitor from them mRef = do
387400 shouldLink <-
388401 if not (isLocal node them)
389402 then return True
390− else liftIO . withMVar (localState node) $
391− return . isJust . (^. localProcessWithId (processLocalId them))
392− case (shouldLink, isLocal node from) of
403+ else isValidLocalIdentifier them
404+ case (shouldLink, isLocal node (ProcessIdentifier from)) of
393405 (True, _) -> -- [Unified: first rule]
394406 case mRef of
395− Just ref -> modify $ monitorsFor them from ^: Set.insert ref
396− Nothing -> modify $ linksForProcess them ^: Set.insert from
407+ Just ref -> modify $ monitorsFor them ^: Set.insert (from, ref)
408+ Nothing -> modify $ linksFor them ^: Set.insert from
397409 (False, True) -> -- [Unified: second rule]
398− notifyDied from them DiedNoProc mRef
410+ notifyDied from them DiedUnknownId mRef
399411 (False, False) -> -- [Unified: third rule]
400412 ncMsg $ sendBinary (NodeIdentifier $ processNodeId from) NCMsg
401413 { ctrlMsgSender = NodeIdentifier (localNodeId node)
402− , ctrlMsgSignal = Died (ProcessIdentifier them) DiedNoProc
414+ , ctrlMsgSignal = Died them DiedUnknownId
403415 }
404416
405417-- [Unified: Table 11]
406−ncEffectUnlink :: ProcessId -> ProcessId -> NC ()
418+ncEffectUnlink :: ProcessId -> Identifier -> NC ()
407419ncEffectUnlink from them = do
408420 node <- ncMsg getLocalNode
409− when (isLocal node from) $ postMessage from $ DidUnlink them
410− modify $ linksForProcess them ^: Set.delete from
421+ when (isLocal node (ProcessIdentifier from)) $
422+ case them of
423+ ProcessIdentifier pid ->
424+ postAsMessage from $ DidUnlinkProcess pid
425+ NodeIdentifier nid ->
426+ postAsMessage from $ DidUnlinkNode nid
427+ SendPortIdentifier cid ->
428+ postAsMessage from $ DidUnlinkPort cid
429+ modify $ linksFor them ^: Set.delete from
411430
412431-- [Unified: Table 11]
413432ncEffectUnmonitor :: ProcessId -> MonitorRef -> NC ()
414433ncEffectUnmonitor from ref = do
415434 node <- ncMsg getLocalNode
416− when (isLocal node from) $ postMessage from $ DidUnmonitor ref
417− modify $ monitorsFor (monitorRefPid ref) from ^: Set.delete ref
418−
419−-- [Unified: Table 12, bottom rule]
420−ncEffectNodeDied :: NodeId -> DiedReason -> NC ()
421−ncEffectNodeDied nid reason = do
422− node <- ncMsg getLocalNode
423− lnks <- gets (^. linksForNode nid)
424− mons <- gets (^. monitorsForNode nid)
425−
426− -- We only need to notify local processes
427− forM_ (Map.toList lnks) $ \(them, uss) -> do
428− let pid = ProcessId nid them
429− forM_ uss $ \us ->
430− when (isLocal node us) $
431− notifyDied us pid reason Nothing
435+ when (isLocal node (ProcessIdentifier from)) $
436+ postAsMessage from $ DidUnmonitor ref
437+ modify $ monitorsFor (monitorRefIdent ref) ^: Set.delete (from, ref)
432438
433− forM_ (Map.toList mons) $ \(them, uss) -> do
434− let pid = ProcessId nid them
435− forM_ (Map.toList uss) $ \(us, refs) ->
436− when (isLocal node us) $
437− forM_ refs $ notifyDied us pid reason . Just
438−
439− modify $ (linksForNode nid ^= Map.empty)
440− . (monitorsForNode nid ^= Map.empty)
439+-- [Unified: Table 12]
440+ncEffectDied :: Identifier -> DiedReason -> NC ()
441+ncEffectDied ident reason = do
442+ node <- ncMsg getLocalNode
443+ (affectedLinks, unaffectedLinks) <- gets (splitNotif ident . (^. links))
444+ (affectedMons, unaffectedMons) <- gets (splitNotif ident . (^. monitors))
441445
442−-- [Unified: Table 12, top rule]
443−ncEffectProcessDied :: ProcessId -> DiedReason -> NC ()
444−ncEffectProcessDied pid reason = do
445− lnks <- gets (^. linksForProcess pid)
446− mons <- gets (^. monitorsForProcess pid)
446+ let localOnly = case ident of NodeIdentifier _ -> True ; _ -> False
447447
448− forM_ lnks $ \us ->
449− notifyDied us pid reason Nothing
448+ forM_ (Map.toList affectedLinks) $ \(them, uss) ->
449+ forM_ uss $ \us ->
450+ when (localOnly <= isLocal node (ProcessIdentifier us)) $
451+ notifyDied us them reason Nothing
450452
451− forM_ (Map.toList mons) $ \(us, refs) ->
452− forM_ refs $
453− notifyDied us pid reason . Just
453+ forM_ (Map.toList affectedMons) $ \(them, refs) ->
454+ forM_ refs $ \(us, ref) ->
455+ when (localOnly <= isLocal node (ProcessIdentifier us)) $
456+ notifyDied us them reason (Just ref)
454457
455− modify $ (linksForProcess pid ^= Set.empty)
456− . (monitorsForProcess pid ^= Map.empty)
458+ modify $ (links ^= unaffectedLinks) . (monitors ^= unaffectedMons)
457459
458460-- [Unified: Table 13]
459461ncEffectSpawn :: ProcessId -> Closure (Process ()) -> SpawnRef -> NC ()
@@ -471,46 +473,48 @@ ncEffectSpawn pid cProc ref = do
471473--------------------------------------------------------------------------------
472474
473475notifyDied :: ProcessId -- ^ Who to notify?
474− -> ProcessId -- ^ Who died?
476+ -> Identifier -- ^ Who died?
475477 -> DiedReason -- ^ How did they die?
476478 -> Maybe MonitorRef -- ^ 'Nothing' for linking
477479 -> NC ()
478480notifyDied dest src reason mRef = do
479481 node <- ncMsg getLocalNode
480− case (isLocal node dest, mRef) of
481− (True, Just ref) ->
482− postMessage dest $ MonitorNotification ref src reason
483− (True, Nothing) ->
484− throwException dest $ LinkException src reason
485− (False, _) ->
482+ case (isLocal node (ProcessIdentifier dest), mRef, src) of
483+ (True, Just ref, ProcessIdentifier pid) ->
484+ postAsMessage dest $ ProcessMonitorNotification ref pid reason
485+ (True, Just ref, NodeIdentifier nid) ->
486+ postAsMessage dest $ NodeMonitorNotification ref nid reason
487+ (True, Just ref, SendPortIdentifier cid) ->
488+ postAsMessage dest $ PortMonitorNotification ref cid reason
489+ (True, Nothing, ProcessIdentifier pid) ->
490+ throwException dest $ ProcessLinkException pid reason
491+ (True, Nothing, NodeIdentifier pid) ->
492+ throwException dest $ NodeLinkException pid reason
493+ (True, Nothing, SendPortIdentifier pid) ->
494+ throwException dest $ PortLinkException pid reason
495+ (False, _, _) ->
486496 -- TODO: why the change in sender? How does that affect 'reconnect' semantics?
487497 -- (see [Unified: Table 10]
488498 ncMsg $ sendBinary (NodeIdentifier $ processNodeId dest) NCMsg
489499 { ctrlMsgSender = NodeIdentifier (localNodeId node)
490− , ctrlMsgSignal = Died (ProcessIdentifier src) reason
500+ , ctrlMsgSignal = Died src reason
491501 }
492502
493503-- | [Unified: Table 8]
494504destNid :: ProcessSignal -> Maybe NodeId
495−destNid (Link pid) =
496− Just . processNodeId $ pid
497−destNid (Unlink pid) =
498− Just . processNodeId $ pid
499−destNid (Monitor pid _) =
500− Just . processNodeId $ pid
501−destNid (Unmonitor ref) =
502− Just . processNodeId . monitorRefPid $ ref
505+destNid (Link ident) = Just $ nodeOf ident
506+destNid (Unlink ident) = Just $ nodeOf ident
507+destNid (Monitor ref) = Just $ nodeOf (monitorRefIdent ref)
508+destNid (Unmonitor ref) = Just $ nodeOf (monitorRefIdent ref)
509+destNid (Spawn _ _) = Nothing
503510-- We don't need to forward 'Died' signals; if monitoring/linking is setup,
504511-- then when a local process dies the monitoring/linking machinery will take
505512-- care of notifying remote nodes
506−destNid (Died _ _) =
507− Nothing
508−destNid (Spawn _ _) =
509− Nothing
513+destNid (Died _ _) = Nothing
510514
511515-- | Check if a process is local to our own node
512−isLocal :: LocalNode -> ProcessId -> Bool
513−isLocal nid pid = processNodeId pid == localNodeId nid
516+isLocal :: LocalNode -> Identifier -> Bool
517+isLocal nid ident = nodeOf ident == localNodeId nid
514518
515519-- | Lookup a local closure
516520unClosure :: Typeable a => Closure a -> NC (Maybe a)
@@ -518,13 +522,35 @@ unClosure (Closure (Static label) env) = do
518522 rtable <- remoteTable <$> ncMsg getLocalNode
519523 return (resolveClosure rtable label env >>= fromDynamic)
520524
525+-- | Check if an identifier refers to a valid local object
526+isValidLocalIdentifier :: Identifier -> NC Bool
527+isValidLocalIdentifier ident = do
528+ node <- ncMsg getLocalNode
529+ liftIO . withMVar (localState node) $ \nSt ->
530+ case ident of
531+ NodeIdentifier nid ->
532+ return $ nid == localNodeId node
533+ ProcessIdentifier pid -> do
534+ let mProc = nSt ^. localProcessWithId (processLocalId pid)
535+ return $ isJust mProc
536+ SendPortIdentifier cid -> do
537+ let pid = sendPortProcessId cid
538+ mProc = nSt ^. localProcessWithId (processLocalId pid)
539+ case mProc of
540+ Nothing -> return False
541+ Just proc -> withMVar (processState proc) $ \pSt -> do
542+ let mCh = pSt ^. typedChannelWithId (sendPortLocalId cid)
543+ return $ isJust mCh
544+
521545--------------------------------------------------------------------------------
522546-- Messages to local processes --
523547--------------------------------------------------------------------------------
524548
525−postMessage :: Serializable a => ProcessId -> a -> NC ()
526−postMessage pid msg = withLocalProc pid $ \p ->
527− enqueue (processQueue p) (createMessage msg)
549+postAsMessage :: Serializable a => ProcessId -> a -> NC ()
550+postAsMessage pid = postMessage pid . createMessage
551+
552+postMessage :: ProcessId -> Message -> NC ()
553+postMessage pid msg = withLocalProc pid $ \p -> enqueue (processQueue p) msg
528554
529555throwException :: Exception e => ProcessId -> e -> NC ()
530556throwException pid e = withLocalProc pid $ \p ->
@@ -544,23 +570,57 @@ withLocalProc pid p = do
544570-- Accessors --
545571--------------------------------------------------------------------------------
546572
547−links :: Accessor NCState (Map NodeId (Map LocalProcessId (Set ProcessId)))
548−links = accessor _links (\lnks st -> st { _links = lnks })
549−
550−monitors :: Accessor NCState (Map NodeId (Map LocalProcessId (Map ProcessId (Set MonitorRef))))
551−monitors = accessor _monitors (\mons st -> st { _monitors = mons })
573+links :: Accessor NCState (Map Identifier (Set ProcessId))
574+links = accessor _links (\ls st -> st { _links = ls })
552575
553−linksForNode :: NodeId -> Accessor NCState (Map LocalProcessId (Set ProcessId))
554−linksForNode nid = links >>> DAC.mapDefault Map.empty nid
576+monitors :: Accessor NCState (Map Identifier (Set (ProcessId, MonitorRef)))
577+monitors = accessor _monitors (\ms st -> st { _monitors = ms })
555578
556−monitorsForNode :: NodeId -> Accessor NCState (Map LocalProcessId (Map ProcessId (Set MonitorRef)))
557−monitorsForNode nid = monitors >>> DAC.mapDefault Map.empty nid
579+linksFor :: Identifier -> Accessor NCState (Set ProcessId)
580+linksFor ident = links >>> DAC.mapDefault Set.empty ident
558581
559−linksForProcess :: ProcessId -> Accessor NCState (Set ProcessId)
560−linksForProcess pid = linksForNode (processNodeId pid) >>> DAC.mapDefault Set.empty (processLocalId pid)
582+monitorsFor :: Identifier -> Accessor NCState (Set (ProcessId, MonitorRef))
583+monitorsFor ident = monitors >>> DAC.mapDefault Set.empty ident
561584
562−monitorsForProcess :: ProcessId -> Accessor NCState (Map ProcessId (Set MonitorRef))
563−monitorsForProcess pid = monitorsForNode (processNodeId pid) >>> DAC.mapDefault Map.empty (processLocalId pid)
564−
565−monitorsFor :: ProcessId -> ProcessId -> Accessor NCState (Set MonitorRef)
566−monitorsFor them us = monitorsForProcess them >>> DAC.mapDefault Set.empty us
585+-- | @splitNotif ident@ splits a notifications map into those
586+-- notifications that should trigger when 'ident' fails and those links that
587+-- should not.
588+--
589+-- There is a hierarchy between identifiers: failure of a node implies failure
590+-- of all processes on that node, and failure of a process implies failure of
591+-- all typed channels to that process. In other words, if 'ident' refers to a
592+-- node, then the /should trigger/ set will include
593+--
594+-- * the notifications for the node specifically
595+-- * the notifications for processes on that node, and
596+-- * the notifications for typed channels to processes on that node.
597+--
598+-- Similarly, if 'ident' refers to a process, the /should trigger/ set will
599+-- include
600+--
601+-- * the notifications for that process specifically and
602+-- * the notifications for typed channels to that process.
603+splitNotif :: Identifier
604+ -> Map Identifier a
605+ -> (Map Identifier a, Map Identifier a)
606+splitNotif ident = Map.partitionWithKey (const . impliesDeathOf ident)
607+ where
608+ -- | Does the death of one entity (node, project, channel) imply the death
609+ -- of another?
610+ impliesDeathOf :: Identifier -- ^ Who died
611+ -> Identifier -- ^ Who's being watched
612+ -> Bool -- ^ Does this death implies the death of the watchee?
613+ NodeIdentifier nid `impliesDeathOf` NodeIdentifier nid' =
614+ nid' == nid
615+ NodeIdentifier nid `impliesDeathOf` ProcessIdentifier pid =
616+ processNodeId pid == nid
617+ NodeIdentifier nid `impliesDeathOf` SendPortIdentifier cid =
618+ processNodeId (sendPortProcessId cid) == nid
619+ ProcessIdentifier pid `impliesDeathOf` ProcessIdentifier pid' =
620+ pid' == pid
621+ ProcessIdentifier pid `impliesDeathOf` SendPortIdentifier cid =
622+ sendPortProcessId cid == pid
623+ SendPortIdentifier cid `impliesDeathOf` SendPortIdentifier cid' =
624+ cid' == cid
625+ _ `impliesDeathOf` _ =
626+ False
distributed-process/tests/TestCH.hs+42−10
@@ -94,26 +94,22 @@ monitorTestProcess theirAddr mOrL un reason monitorSetup done =
9494 case (un, mRef) of
9595 (True, Nothing) -> do
9696 unlink theirAddr
97− DidUnlink pid <- expect
98− True <- return $ pid == theirAddr
9997 liftIO $ putMVar done ()
10098 (True, Just ref) -> do
10199 unmonitor ref
102− DidUnmonitor ref' <- expect
103− True <- return $ ref == ref'
104100 liftIO $ putMVar done ()
105101 (False, ref) -> do
106− MonitorNotification ref' pid reason' <- expect
102+ ProcessMonitorNotification ref' pid reason' <- expect
107103 True <- return $ Just ref' == ref && pid == theirAddr && mOrL && reason == reason'
108104 liftIO $ putMVar done ()
109105 )
110− (\(LinkException pid reason') -> do
106+ (\(ProcessLinkException pid reason') -> do
111107 True <- return $ pid == theirAddr && not mOrL && not un && reason == reason'
112108 liftIO $ putMVar done ()
113109 )
114110
115111
116−-- | Monitor an unreachable node
112+-- | Monitor a process on an unreachable node
117113testMonitorUnreachable :: NT.Transport -> Bool -> Bool -> IO ()
118114testMonitorUnreachable transport mOrL un = do
119115 deadProcess <- newEmptyMVar
@@ -194,7 +190,7 @@ testMonitorLocalDeadProcess transport mOrL un = do
194190 theirAddr <- readMVar processAddr
195191 readMVar processDead
196192 runProcess localNode $ do
197− monitorTestProcess theirAddr mOrL un DiedNoProc Nothing done
193+ monitorTestProcess theirAddr mOrL un DiedUnknownId Nothing done
198194
199195 takeMVar done
200196
@@ -215,7 +211,7 @@ testMonitorRemoteDeadProcess transport mOrL un = do
215211 theirAddr <- readMVar processAddr
216212 readMVar processDead
217213 runProcess localNode $ do
218− monitorTestProcess theirAddr mOrL un DiedNoProc Nothing done
214+ monitorTestProcess theirAddr mOrL un DiedUnknownId Nothing done
219215
220216 takeMVar done
221217
@@ -493,10 +489,41 @@ testTerminate transport = do
493489
494490 runProcess localNode $ do
495491 ref <- monitor pid
496− MonitorNotification ref' pid' (DiedException ex) <- expect
492+ ProcessMonitorNotification ref' pid' (DiedException ex) <- expect
497493 True <- return $ ref == ref' && pid == pid' && ex == show ProcessTerminationException
498494 return ()
499495
496+testMonitorNode :: NT.Transport -> IO ()
497+testMonitorNode transport = do
498+ [node1, node2] <- replicateM 2 $ newLocalNode transport initRemoteTable
499+
500+ closeLocalNode node1
501+
502+ runProcess node2 $ do
503+ ref <- monitorNode (localNodeId node1)
504+ NodeMonitorNotification ref' nid DiedDisconnect <- expect
505+ True <- return $ ref == ref' && nid == localNodeId node1
506+ return ()
507+
508+testMonitorChannel :: NT.Transport -> IO ()
509+testMonitorChannel transport = do
510+ [node1, node2] <- replicateM 2 $ newLocalNode transport initRemoteTable
511+ gotNotification <- newEmptyMVar
512+
513+ pid <- forkProcess node1 $ do
514+ sport <- expect :: Process (SendPort ())
515+ ref <- monitorPort sport
516+ PortMonitorNotification ref' port' DiedNormal <- expect
517+ return $ ref' == ref && port' == sendPortId sport
518+ liftIO $ putMVar gotNotification ()
519+
520+ runProcess node2 $ do
521+ (sport, _) <- newChan :: Process (SendPort (), ReceivePort ())
522+ send pid sport
523+ liftIO $ threadDelay 100000
524+
525+ takeMVar gotNotification
526+
500527main :: IO ()
501528main = do
502529 Right transport <- createTransport "127.0.0.1" "8080" defaultTCPParameters
@@ -509,6 +536,8 @@ main = do
509536 , ("TypedChannnels", testTypedChannels transport)
510537 , ("MergeChannels", testMergeChannels transport)
511538 , ("TestTerminate", testTerminate transport)
539+ -- Monitoring processes
540+ --
512541 -- The "missing" combinations in the list below don't make much sense, as
513542 -- we cannot guarantee that the monitor reply or link exception will not
514543 -- happen before the unmonitor or unlink
@@ -530,4 +559,7 @@ main = do
530559 , ("UnlinkNormalTermination", testMonitorNormalTermination transport False True)
531560 , ("UnlinkAbnormalTermination", testMonitorAbnormalTermination transport False True)
532561 , ("UnlinkDisconnect", testMonitorDisconnect transport False True)
562+ -- Monitoring nodes and channels
563+ , ("MonitorNode", testMonitorNode transport)
564+ , ("MonitorChannel", testMonitorChannel transport)
533565 ]
distributed-process/tests/TestClosure.hs+3−3
@@ -235,10 +235,10 @@ testSpawnSupervised transport rtable = do
235235 forkProcess node2 $ do
236236 [super, child] <- liftIO $ mapM readMVar [superPid, childPid]
237237 ref <- monitor child
238− MonitorNotification ref' pid' (DiedException e) <- expect
238+ ProcessMonitorNotification ref' pid' (DiedException e) <- expect
239239 True <- return $ ref' == ref
240240 && pid' == child
241− && e == show (LinkException super (DiedException (show supervisorDeath)))
241+ && e == show (ProcessLinkException super (DiedException (show supervisorDeath)))
242242 liftIO $ putMVar thirdProcessDone ()
243243
244244 takeMVar thirdProcessDone
@@ -251,7 +251,7 @@ testSpawnInvalid transport rtable = do
251251 node <- newLocalNode transport rtable
252252 runProcess node $ do
253253 (pid, ref) <- spawnMonitor (localNodeId node) (Closure (Static (UserStatic "ThisDoesNotExist")) BSL.empty)
254− MonitorNotification ref' pid' _reason <- expect
254+ ProcessMonitorNotification ref' pid' _reason <- expect
255255 -- Depending on the exact interleaving, reason might be NoProc or the exception thrown by the absence of the static closure
256256 True <- return $ ref' == ref && pid == pid'
257257 return ()