Skip to content

Commit d59ac11

Browse files
Merge pull request haskell-distributed#267 from haskell-distributed/fd/trace-loop
Avoid loop when tracing received messages.
2 parents c18f525 + d8c36b5 commit d59ac11

File tree

3 files changed

+108
-5
lines changed

3 files changed

+108
-5
lines changed

distributed-process-tests/distributed-process-tests.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ library
3535
network >= 2.5 && < 2.7,
3636
random >= 1.0 && < 1.2,
3737
rematch >= 0.1.2.1,
38+
setenv >= 0.1.1.3,
3839
test-framework >= 0.6 && < 0.9,
3940
test-framework-hunit >= 0.2.0 && < 0.4,
4041
stm

distributed-process-tests/src/Control/Distributed/Process/Tests/Tracing.hs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ module Control.Distributed.Process.Tests.Tracing (tests) where
55
import Control.Distributed.Process.Tests.Internal.Utils
66
import Network.Transport.Test (TestTransport(..))
77

8+
import Control.Applicative ((<*))
89
import Control.Concurrent (threadDelay)
910
import Control.Concurrent.MVar
1011
( MVar
@@ -19,16 +20,24 @@ import Control.Distributed.Process.Debug
1920
import Control.Distributed.Process.Management
2021
( MxEvent(..)
2122
)
23+
import qualified Control.Exception as IO (bracket)
24+
import Data.List (isPrefixOf, isSuffixOf)
2225

2326
#if ! MIN_VERSION_base(4,6,0)
2427
import Prelude hiding (catch, log)
28+
#else
29+
import Prelude hiding ((<*))
2530
#endif
2631

2732
import Test.Framework
2833
( Test
2934
, testGroup
3035
)
3136
import Test.Framework.Providers.HUnit (testCase)
37+
import System.Environment (getEnvironment)
38+
-- These are available in System.Environment only since base 4.7
39+
import System.SetEnv (setEnv, unsetEnv)
40+
3241

3342
testSpawnTracing :: TestResult Bool -> Process ()
3443
testSpawnTracing result = do
@@ -282,6 +291,82 @@ testRemoteTraceRelay TestTransport{..} result =
282291
-- and just to be polite...
283292
liftIO $ closeLocalNode node2
284293

294+
-- | Sets the value of an environment variable while executing the given IO
295+
-- computation and restores the preceeding value upon completion.
296+
withEnv :: String -> String -> IO a -> IO a
297+
withEnv var val =
298+
IO.bracket (fmap (lookup var) getEnvironment <* setEnv var val)
299+
(maybe (unsetEnv var) (setEnv var))
300+
. const
301+
302+
-- | Tests that one and only one interesting trace message is produced when a
303+
-- given action is performed. A message is considered interesting when the given
304+
-- function return @True@.
305+
testSystemLoggerMsg :: TestTransport
306+
-> Process a
307+
-> (a -> String -> Bool)
308+
-> IO ()
309+
testSystemLoggerMsg t action interestingMessage =
310+
withEnv "DISTRIBUTED_PROCESS_TRACE_CONSOLE" "yes" $
311+
withEnv "DISTRIBUTED_PROCESS_TRACE_FLAGS" "pdnusrl" $ do
312+
n <- newLocalNode (testTransport t) initRemoteTable
313+
314+
runProcess n $ do
315+
self <- getSelfPid
316+
reregister "trace.logger" self
317+
a <- action
318+
let interestingMessage' (_ :: String, msg) = interestingMessage a msg
319+
-- Wait for the trace message.
320+
receiveWait [ matchIf interestingMessage' $ const $ return () ]
321+
-- Only one interesting message should arrive.
322+
Nothing <- receiveTimeout 100000
323+
[ matchIf interestingMessage' $ const $ return () ]
324+
return ()
325+
326+
327+
-- | Tests that one and only one trace message is produced when a message is
328+
-- received.
329+
testSystemLoggerMxReceive :: TestTransport -> IO ()
330+
testSystemLoggerMxReceive t = testSystemLoggerMsg t
331+
(getSelfPid >>= flip send ())
332+
(\_ msg -> "MxReceived" `isPrefixOf` msg
333+
-- discard traces of internal messages
334+
&& not (":: RegisterReply" `isSuffixOf` msg)
335+
)
336+
337+
-- | Tests that one and only one trace message is produced when a message is
338+
-- sent.
339+
testSystemLoggerMxSent :: TestTransport -> IO ()
340+
testSystemLoggerMxSent t = testSystemLoggerMsg t
341+
(getSelfPid >>= flip send ())
342+
(const $ isPrefixOf "MxSent")
343+
344+
-- | Tests that one and only one trace message is produced when a process dies.
345+
testSystemLoggerMxProcessDied :: TestTransport -> IO ()
346+
testSystemLoggerMxProcessDied t = testSystemLoggerMsg t
347+
(spawnLocal $ return ())
348+
(\pid -> isPrefixOf $ "MxProcessDied " ++ show pid)
349+
350+
-- | Tests that one and only one trace message appears when a process spawns.
351+
testSystemLoggerMxSpawned :: TestTransport -> IO ()
352+
testSystemLoggerMxSpawned t = testSystemLoggerMsg t
353+
(spawnLocal $ return ())
354+
(\pid -> isPrefixOf $ "MxSpawned " ++ show pid)
355+
356+
-- | Tests that one and only one trace message appears when a process is
357+
-- registered.
358+
testSystemLoggerMxRegistered :: TestTransport -> IO ()
359+
testSystemLoggerMxRegistered t = testSystemLoggerMsg t
360+
(getSelfPid >>= register "a" >> getSelfPid)
361+
(\self -> isPrefixOf $ "MxRegistered " ++ show self ++ " " ++ show "a")
362+
363+
-- | Tests that one and only one trace message appears when a process is
364+
-- unregistered.
365+
testSystemLoggerMxUnRegistered :: TestTransport -> IO ()
366+
testSystemLoggerMxUnRegistered t = testSystemLoggerMsg t
367+
(getSelfPid >>= register "a" >> unregister "a" >> getSelfPid)
368+
(\self -> isPrefixOf $ "MxUnRegistered " ++ show self ++ " " ++ show "a")
369+
285370
tests :: TestTransport -> IO [Test]
286371
tests testtrans@TestTransport{..} = do
287372
node1 <- newLocalNode testTransport initRemoteTable
@@ -323,4 +408,12 @@ tests testtrans@TestTransport{..} = do
323408
(synchronisedAssertion
324409
"expected blah"
325410
node1 True (testRemoteTraceRelay testtrans) lock)
411+
, testGroup "SystemLoggerTracer"
412+
[ testCase "MxReceive" $ testSystemLoggerMxReceive testtrans
413+
, testCase "MxSent" $ testSystemLoggerMxSent testtrans
414+
, testCase "MxProcessDied" $ testSystemLoggerMxProcessDied testtrans
415+
, testCase "MxSpawned" $ testSystemLoggerMxSpawned testtrans
416+
, testCase "MxRegistered" $ testSystemLoggerMxRegistered testtrans
417+
, testCase "MxUnRegistered" $ testSystemLoggerMxUnRegistered testtrans
418+
]
326419
] ]

src/Control/Distributed/Process/Node.hs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -662,10 +662,13 @@ instance Show ProcessKillException where
662662
"killed-by=" ++ show pid ++ ",reason=" ++ reason
663663

664664
ncSendToProcess :: ProcessId -> Message -> NC ()
665-
ncSendToProcess pid msg = do
665+
ncSendToProcess = ncSendToProcessAndTrace True
666+
667+
ncSendToProcessAndTrace :: Bool -> ProcessId -> Message -> NC ()
668+
ncSendToProcessAndTrace shouldTrace pid msg = do
666669
node <- ask
667670
if processNodeId pid == localNodeId node
668-
then ncEffectLocalSend node pid msg
671+
then ncEffectLocalSendAndTrace shouldTrace node pid msg
669672
else liftIO $ sendBinary node
670673
(NodeIdentifier $ localNodeId node)
671674
(NodeIdentifier $ processNodeId pid)
@@ -946,14 +949,20 @@ ncEffectNamedSend :: String -> Message -> NC ()
946949
ncEffectNamedSend label msg = do
947950
mPid <- gets (^. registeredHereFor label)
948951
-- If mPid is Nothing, we just ignore the named send (as per Table 14)
949-
forM_ mPid (`ncSendToProcess` msg)
952+
forM_ mPid $ \to ->
953+
-- If this is a trace message we don't trace it to avoid entering a loop
954+
-- where trace messages produce more trace messages.
955+
ncSendToProcessAndTrace (label /= "trace.logger") to msg
950956

951957
-- [Issue #DP-20]
952958
ncEffectLocalSend :: LocalNode -> ProcessId -> Message -> NC ()
953-
ncEffectLocalSend node to msg =
959+
ncEffectLocalSend = ncEffectLocalSendAndTrace True
960+
961+
ncEffectLocalSendAndTrace :: Bool -> LocalNode -> ProcessId -> Message -> NC ()
962+
ncEffectLocalSendAndTrace shouldTrace node to msg =
954963
liftIO $ withLocalProc node to $ \p -> do
955964
enqueue (processQueue p) msg
956-
trace node (MxReceived to msg)
965+
when shouldTrace $ trace node (MxReceived to msg)
957966

958967
-- [Issue #DP-20]
959968
ncEffectLocalPortSend :: SendPortId -> Message -> NC ()

0 commit comments

Comments
 (0)