@@ -106,7 +106,7 @@ import Control.Distributed.Process.Internal.Types
106 , LocalProcessId(..)
106 , LocalProcessId(..)
107 , ProcessId(..)
107 , ProcessId(..)
108 , LocalNode(..)
108 , LocalNode(..)
109− , Tracer(..)
109+ , MxEventBus(..)
110 , LocalNodeState(..)
110 , LocalNodeState(..)
111 , LocalProcess(..)
111 , LocalProcess(..)
112 , LocalProcessState(..)
112 , LocalProcessState(..)
@@ -160,8 +160,7 @@ import Control.Distributed.Process.Internal.Trace.Types
160 , enableTrace
160 , enableTrace
162import Control.Distributed.Process.Internal.Trace.Tracer
162import Control.Distributed.Process.Internal.Trace.Tracer
164− , defaultTracer
163+ ( defaultTracer
166import Control.Distributed.Process.Serializable (Serializable)
165import Control.Distributed.Process.Serializable (Serializable)
167import Control.Distributed.Process.Internal.Messaging
166import Control.Distributed.Process.Internal.Messaging
@@ -179,13 +178,16 @@ import Control.Distributed.Process.Internal.Primitives
180 , unwrapMessage
179 , unwrapMessage
182−import Control.Distributed.Process.Internal.Types (SendPort)
181+import Control.Distributed.Process.Internal.Types (SendPort, Tracer(..))
183import qualified Control.Distributed.Process.Internal.Closure.BuiltIn as BuiltIn (remoteTable)
182import qualified Control.Distributed.Process.Internal.Closure.BuiltIn as BuiltIn (remoteTable)
184import Control.Distributed.Process.Internal.WeakTQueue (TQueue, writeTQueue)
183import Control.Distributed.Process.Internal.WeakTQueue (TQueue, writeTQueue)
185import qualified Control.Distributed.Process.Internal.StrictContainerAccessors as DAC
184import qualified Control.Distributed.Process.Internal.StrictContainerAccessors as DAC
186 ( mapMaybe
185 ( mapMaybe
187 , mapDefault
186 , mapDefault
188+import Control.Distributed.Process.Management.Agent
189import System.Environment (getEnv)
191import System.Environment (getEnv)
190import Unsafe.Coerce
192import Unsafe.Coerce
@@ -222,10 +224,10 @@ createBareLocalNode endPoint rtable = do
222 , localEndPoint = endPoint
224 , localEndPoint = endPoint
223 , localState = state
225 , localState = state
224 , localCtrlChan = ctrlChan
226 , localCtrlChan = ctrlChan
225− , localTracer = InactiveTracer
227+ , localEventBus = MxEventBusInitialising
226 , remoteTable = rtable
228 , remoteTable = rtable
228− tracedNode <- startTracing node
230+ tracedNode <- startMxAgent node
230 -- Once the NC terminates, the endpoint isn't much use,
232 -- Once the NC terminates, the endpoint isn't much use,
231 void $ forkIO $ Exception.finally (runNodeController tracedNode)
233 void $ forkIO $ Exception.finally (runNodeController tracedNode)
@@ -243,38 +245,25 @@ createBareLocalNode endPoint rtable = do
243 , ctrlMsgSignal = SigShutdown
245 , ctrlMsgSignal = SigShutdown
246−startTracing :: LocalNode -> IO LocalNode
248+startMxAgent :: LocalNode -> IO LocalNode
247−startTracing node =
249+startMxAgent node = do
248− -- TODO: use tryGetEnv once we drop support for GHC 7.2.x
250− (getEnv "DISTRIBUTED_PROCESS_TRACE_ENABLED" >> procTracer node)
251− (\(_ :: IOError) -> return node)
252− where procTracer :: LocalNode -> IO LocalNode
254− -- see note [tracer/forkProcess races]
250+ -- see note [tracer/forkProcess races]
251+ let fork = forkProcess node
255− mv <- MVar.newEmptyMVar
252+ mv <- MVar.newEmptyMVar
256− pid <- forkProcess n (traceController mv)
253+ pid <- fork $ mxAgentController fork mv
257− wqRef <- MVar.takeMVar mv
254+ (tracer, wqRef, mxNew) <- MVar.takeMVar mv
258− return n { localTracer = (ActiveTracer pid wqRef) }
255+ return node { localEventBus = (MxEventBus pid tracer wqRef mxNew) }
260−startDefaultTracer :: LocalNode -> IO (Maybe ProcessId)
257+startDefaultTracer :: LocalNode -> IO ()
261−startDefaultTracer node =
258+startDefaultTracer node' = do
262− Exception.catch
259+ let t = localEventBus node'
263− (getEnv "DISTRIBUTED_PROCESS_TRACE_ENABLED" >> go node)
264− (\(_ :: IOError) -> return Nothing)
265− where go :: LocalNode -> IO (Maybe ProcessId)
267− registerTraceController node'
268− pid <- forkProcess node' defaultTracer
269− enableTrace (localTracer node') pid
272− registerTraceController :: LocalNode -> IO ()
273− registerTraceController n =
274− let t = localTracer n in
275− case t of
260+ case t of
276− InactiveTracer -> return ()
261+ MxEventBus _ (ActiveTracer pid _) _ _ -> do
277− (ActiveTracer pid _) -> runProcess n $ register "trace.controller" pid
262+ runProcess node' $ register "trace.controller" pid
263+ pid' <- forkProcess node' defaultTracer
264+ enableTrace (localEventBus node') pid'
265+ runProcess node' $ register "tracer.initial" pid'
279-- | Start and register the service processes on a node
268-- | Start and register the service processes on a node
280startServiceProcesses :: LocalNode -> IO ()
269startServiceProcesses :: LocalNode -> IO ()
@@ -283,11 +272,7 @@ startServiceProcesses node = do
283 -- the default tracer first, even though it might @nsend@ to the logger
272 -- the default tracer first, even though it might @nsend@ to the logger
284 -- before /that/ process has started - this is a totally harmless race
273 -- before /that/ process has started - this is a totally harmless race
285 -- however, so we deliberably ignore it
274 -- however, so we deliberably ignore it
286− mPid <- startDefaultTracer node
275+ startDefaultTracer node
288− Nothing -> return ()
289− Just pid -> runProcess node $ register "tracer.initial" pid
291 logger <- forkProcess node loop
276 logger <- forkProcess node loop
292 runProcess node $ register "logger" logger
277 runProcess node $ register "logger" logger
@@ -401,7 +386,7 @@ forkProcess node proc = modifyMVar (localState node) startProcess
402-- Our startTracing function uses forkProcess to start the trace controller
387-- Our startTracing function uses forkProcess to start the trace controller
403-- process, and of course forkProcess attempts to call traceEvent once the
388-- process, and of course forkProcess attempts to call traceEvent once the
404−-- process has started. This is harmless, as the localTracer is not updated
389+-- process has started. This is harmless, as the localEventBus is not updated
405-- until /after/ the initial forkProcess completes, so the first call to
390-- until /after/ the initial forkProcess completes, so the first call to
406-- traceEvent behaves as if tracing were disabled (i.e., it is ignored).
391-- traceEvent behaves as if tracing were disabled (i.e., it is ignored).
@@ -607,7 +592,7 @@ instance Show ProcessKillException where
607-- Tracing/Debugging --
592-- Tracing/Debugging --
608--------------------------------------------------------------------------------
593--------------------------------------------------------------------------------
610−-- [Issue #104]
595+-- [Issue #104 / DP-13]
612traceNotifyDied :: LocalNode -> Identifier -> DiedReason -> NC ()
597traceNotifyDied :: LocalNode -> Identifier -> DiedReason -> NC ()
613traceNotifyDied node ident reason =
598traceNotifyDied node ident reason =
@@ -628,8 +613,8 @@ traceEventFmtIO node fmt args =
628trace :: LocalNode -> TraceEvent -> IO ()
613trace :: LocalNode -> TraceEvent -> IO ()
629trace node ev = withLocalTracer node $ \t -> traceEvent t ev
614trace node ev = withLocalTracer node $ \t -> traceEvent t ev
631−withLocalTracer :: LocalNode -> (Tracer -> IO ()) -> IO ()
616+withLocalTracer :: LocalNode -> (MxEventBus -> IO ()) -> IO ()
632−withLocalTracer node act = act (localTracer node)
617+withLocalTracer node act = act (localEventBus node)
634--------------------------------------------------------------------------------
619--------------------------------------------------------------------------------
635-- Core functionality --
620-- Core functionality --