git.iko.soy/distributed-process
on master help sign in
Merge branch 'master' into mx-fix2
commit9de6c07cf6b79b632d2e18171c335fb48baa400d authorTim Watson <watson.timothy@gmail.com> dateThu 22 Nov 2018, 16:19 (8 years ago) parentbb91973d215728
5 files changed+116−7
distributed-process-tests/distributed-process-tests.cabal+1−1 distributed-process-tests/src/Control/Distributed/Process/Tests/CH.hs+73−2 distributed-process.cabal+1−1 src/Control/Distributed/Process/Internal/Primitives.hs+7−1 src/Control/Distributed/Process/Management.hs+34−2
distributed-process-tests/distributed-process-tests.cabal+1−1
@@ -6,7 +6,7 @@ description: Tests and test suite for Cloud Haskell libraries.
66license: BSD3
77license-file: LICENSE
88Author: Duncan Coutts, Nicolas Wu, Edsko de Vries
9−Maintainer: Facundo Domínguez <facundo.dominguez@tweag.io>
9+Maintainer: Tim Watson <watson.timothy@gmail.com>
1010copyright: Well-Typed LLP
1111category: Control, Cloud Haskell
1212build-type: Simple
distributed-process-tests/src/Control/Distributed/Process/Tests/CH.hs+73−2
@@ -46,11 +46,11 @@ import Control.Distributed.Process.Debug
4646import Control.Distributed.Process.Management.Internal.Types
4747import Control.Distributed.Process.Tests.Internal.Utils (shouldBe, pause)
4848import Control.Distributed.Process.Serializable (Serializable)
49−
49+import Data.Maybe (isNothing)
5050import Test.HUnit (Assertion, assertBool, assertFailure)
5151import Test.Framework (Test, testGroup)
5252import Test.Framework.Providers.HUnit (testCase)
53−import Control.Rematch hiding (match)
53+import Control.Rematch hiding (match, isNothing)
5454import Control.Rematch.Run (Match(..))
5555
5656newtype Ping = Ping ProcessId
@@ -1272,6 +1272,76 @@ testReceiveChanFeatures TestTransport{..} = do
12721272
12731273 takeMVar done
12741274
1275+testChanLifecycle :: TestTransport -> Assertion
1276+testChanLifecycle TestTransport{..} = let delay = 3000000 in do
1277+ result <- newEmptyMVar
1278+ tchMV <- newEmptyMVar
1279+ localNode <- newLocalNode testTransport initRemoteTable
1280+ runProcess localNode $ do
1281+
1282+ pid <- spawnLocal $ do tCh <- newChan :: Process (SendPort (), ReceivePort ())
1283+ liftIO $ putMVar tchMV tCh
1284+ expect :: Process ()
1285+ let (sp, _) = tCh
1286+ sendChan sp ()
1287+ expect :: Process ()
1288+
1289+ mRefPid <- monitor pid
1290+
1291+ cPid <- spawnLocal $ do
1292+ (sp', rp) <- liftIO $ takeMVar tchMV
1293+ -- say "picked up our test channel"
1294+ send pid ()
1295+ -- say "told pid to continue"
1296+ res <- receiveChanTimeout delay rp
1297+ case res of
1298+ Nothing -> say "initial chan () missing!" >> (liftIO $ putMVar result False)
1299+ Just () -> do mr <- monitor pid
1300+ pause 10000
1301+ -- say "sending pid a second () will cause it to exit"
1302+ send pid ()
1303+
1304+ -- say "make sure we see a DOWN notification for pid having stopped"
1305+ receiveWait [ match (\(_ :: ProcessMonitorNotification) -> return ()) ]
1306+
1307+ -- now that pid has died, the send port should be useless...
1308+ liftIO $ putMVar tchMV (sp', rp)
1309+
1310+ -- let's verify that we do not see the message from our
1311+ -- parent process on the channel, once pid has died...
1312+ recv <- receiveChanTimeout delay rp
1313+ -- say $ "finished waiting for second (), writing result" ++ (show recv)
1314+ liftIO $ putMVar result $ isNothing recv
1315+
1316+ mRefCPid <- monitor cPid
1317+
1318+ receiveWait
1319+ [ matchIf (\(ProcessMonitorNotification r _ _) -> r == mRefPid)
1320+ (\_ -> return ())
1321+ ]
1322+
1323+ -- say "seen first pid die..."
1324+
1325+ (sendPort, _) <- liftIO $ takeMVar tchMV
1326+ sendChan sendPort ()
1327+ -- say "sent () after owning pid died"
1328+
1329+ -- let cPid know we've written to the channel...
1330+ send cPid ()
1331+
1332+ receiveWait
1333+ [ matchIf (\(ProcessMonitorNotification r _ _) -> r == mRefCPid)
1334+ (\_ -> return ())
1335+ ]
1336+
1337+ -- say "seen both pids die now..."
1338+
1339+ -- and wait on the result back in IO land...
1340+ testRes <- takeMVar result
1341+ -- runProcess localNode $ say "got result..."
1342+ assertBool "Expected sending on the channel to fail, but received data!" testRes
1343+
1344+
12751345testKillLocal :: TestTransport -> Assertion
12761346testKillLocal TestTransport{..} = do
12771347 localNode <- newLocalNode testTransport initRemoteTable
@@ -1736,6 +1806,7 @@ tests testtrans = return [
17361806 , testCase "MatchMessageUnwrap" (testMatchMessageWithUnwrap testtrans)
17371807 , testCase "ReceiveChanTimeout" (testReceiveChanTimeout testtrans)
17381808 , testCase "ReceiveChanFeatures" (testReceiveChanFeatures testtrans)
1809+ , testCase "ChanLifecycle" (testChanLifecycle testtrans)
17391810 , testCase "KillLocal" (testKillLocal testtrans)
17401811 , testCase "KillRemote" (testKillRemote testtrans)
17411812 , testCase "Die" (testDie testtrans)
distributed-process.cabal+1−1
@@ -6,7 +6,7 @@ License: BSD3
66License-File: LICENSE
77Copyright: Well-Typed LLP, Tweag I/O Limited
88Author: Duncan Coutts, Nicolas Wu, Edsko de Vries
9−Maintainer: Facundo Domínguez <facundo.dominguez@tweag.io>
9+Maintainer: Tim Watson <watson.timothy@gmail.com>
1010Stability: experimental
1111Homepage: http://haskell-distributed.github.com/
1212Bug-Reports: https://github.com/haskell-distributed/distributed-process/issues
src/Control/Distributed/Process/Internal/Primitives.hs+7−1
@@ -307,7 +307,13 @@ expect = receiveWait [match return]
307307-- Channels --
308308--------------------------------------------------------------------------------
309309
310−-- | Create a new typed channel
310+-- | Create a new typed channel, bound to the calling Process
311+--
312+-- Note that the channel is bound to the lifecycle of the process that evaluates
313+-- this function, such that when it dies/exits, the channel will no longer
314+-- function, but will remain accessible. Thus reading from the ReceivePort will
315+-- fail silently thereafter, blocking indefinitely (unless a timeout is used).
316+--
311317newChan :: Serializable a => Process (SendPort a, ReceivePort a)
312318newChan = do
313319 proc <- ask
src/Control/Distributed/Process/Management.hs+34−2
@@ -76,6 +76,40 @@
7676--
7777-- * Whether messages will be taken from the mailbox first, or the event bus.
7878--
79+-- Since the event bus uses STM broadcast channels to communicate with agents,
80+-- no message written to the bus successfully can be lost.
81+--
82+-- Agents can also receive messages via their mailboxes - these are subject to
83+-- the same guarantees as all inter-process message sending.
84+--
85+-- Messages dispatched on an STM broadcast channel (i.e., management event bus)
86+-- are guaranteed to be delivered with the same FIFO ordering guarantees that
87+-- exist between two communicating processes, such that communication from the
88+-- node controller's threads (i.e., MxEvent's) will never be re-ordered, but
89+-- messages dispatched to the event bus by other processes (including, but not
90+-- limited to agents) are only guaranteed to be ordered between one sender and
91+-- one receiver.
92+--
93+-- No guarantee exists for the ordering in which messages sent to an agent's
94+-- mailbox will be delivered, vs messages dispatched via the event bus.
95+--
96+-- Because of the above, there are no ordering guarantees for messages sent
97+-- between agents, or for processes to agents, except for those that apply to
98+-- messages sent between regular processes, since agents are
99+-- implemented as such.
100+--
101+-- The event bus is serial and single threaded. Anything that is published by
102+-- the node controller will be seen in FIFO order. There are no ordering
103+-- guarantees pertaining to entries published to the event bus by other
104+-- processes or agents.
105+--
106+-- It should not be possible to see, for example, an @MxReceived@ before the
107+-- corresponding @MxSent@ event, since the places where we issue the @MxSent@
108+-- write directly to the event bus (using STM) in the calling (green) thread,
109+-- before dispatching instructions to the node controller to perform the
110+-- necessary routing to deliver the message to a process (or registered name,
111+-- or typed channel) locally or remotely.
112+--
79113-- [Management Data API]
80114--
81115-- Both management agents and clients of the API have access to a variety of
@@ -144,8 +178,6 @@
144178-- > monitorNames = getSelfPid >>= nsend "name-monitor"
145179-- > monitorNames2 = getSelfPid >>= mxNotify
146180--
147−-- For some real-world examples, see the distributed-process-platform package.
148−--
149181-- [Performance, Stablity and Scalability]
150182--
151183-- /Management Agents/ offer numerous advantages over regular processes: