Skip to content

Commit d8c36b5

Browse files
Avoid loop when tracing received messages.
When a trace message was sent to "trace.logger", the NC would produce a trace message to indicate the arrival of it, this new trace message would in turn have the NC produce another trace message and so on. In this patch the NC does not produce a trace message when the destination is the "trace.logger" process.
1 parent c18f525 commit d8c36b5

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)