@@ -94,9 +94,14 @@ module Control.Distributed.Process.Debug
9494 , disableTrace
9595 , disableTraceAsync
9696 , withTracer
97+ , withFlags
98+ , getTraceFlags
9799 , setTraceFlags
98100 , setTraceFlagsAsync
99101 , defaultTraceFlags
102+ , Tracer.traceOn
103+ , Tracer.traceOnly
104+ , Tracer.traceOff
100105 -- * Debugging
101106 , startTracer
102107 , stopTracer
@@ -128,6 +133,7 @@ import Control.Distributed.Process.Internal.Primitives
128133 , finally
129134 , try
130135 , monitor
136+ , say
131137 )
132138import Control.Distributed.Process.Internal.Types
133139 ( Tracer(..)
@@ -161,6 +167,10 @@ import qualified Control.Distributed.Process.Internal.Trace.Primitives as Tracer
161167 , disableTraceSync
162168 , setTraceFlags
163169 , setTraceFlagsSync
170+ , getTraceFlags
171+ , traceOn
172+ , traceOff
173+ , traceOnly
164174 )
165175import Control.Distributed.Process.Node
166176import Control.Distributed.Process.Serializable
@@ -189,7 +199,6 @@ import Prelude hiding (catch)
189199-- reregister the original (prior) tracer pid before terminating.
190200startTracer :: (TraceEvent -> Process ()) -> Process ProcessId
191201startTracer handler = do
192− (sp, rp) <- newChan
193202 withRegisteredTracer $ \pid -> do
194203 node <- processNode <$> ask
195204 newPid <- liftIO $ forkProcess node $ do
@@ -200,9 +209,8 @@ startTracer handler = do
200209 -- close succession, due to scheduling
201210 finally (traceProxy pid handler)
202211 (resetTracer pid)
203− enableTrace newPid
204− sendChan sp newPid
205− receiveChan rp
212+ enableTrace newPid -- invokes sync + registration
213+ return newPid
206214
207215-- | Evaluate @proc@ with tracing enabled via @handler@, and immediately
208216-- disable tracing thereafter, before giving the result (or exception
@@ -212,22 +220,38 @@ withTracer :: forall a.
212220 -> Process a
213221 -> Process (Either SomeException a)
214222withTracer handler proc = do
223+ say "starting new tracer"
215224 tracer <- startTracer handler
216− finally (try proc)
225+ finally (try ((say "evaluating tracer proc...") >> proc))
217226 (stopTracing tracer)
218227 where
219228 stopTracing :: ProcessId -> Process ()
220229 stopTracing tracer = do
230+ say "stopping tracer"
221231 ref <- monitor tracer
222232 stopTracer
223233 receiveWait [
224234 matchIf (\(ProcessMonitorNotification ref' _ _) -> ref == ref')
225235 (\_ -> return ())
226236 ]
237+ say "stopped..."
238+
239+-- | Evaluate @proc@ with the supplied flags enabled. Any previously set
240+-- flags are restored immediately afterwards.
241+withFlags :: forall a.
242+ TraceFlags
243+ -> Process a
244+ -> Process (Either SomeException a)
245+withFlags flags proc = do
246+ (sp, rp) <- newChan
247+ withLocalTracer $ \t -> liftIO $ Tracer.getTraceFlags t sp
248+ oldFlags <- receiveChan rp
249+ finally (setTraceFlags flags >> try proc)
250+ (setTraceFlags oldFlags >> say "exit withFlags")
227251
228252traceProxy :: ProcessId -> (TraceEvent -> Process ()) -> Process ()
229253traceProxy pid act = do
230− getSelfPid >>= reregister "tracer" -- registration is synchronous
254+ say "tracing has started"
231255 proxy pid $ \(ev :: TraceEvent) ->
232256 case ev of
233257 (TraceEvTakeover _) -> die "takeover"
@@ -235,7 +259,9 @@ traceProxy pid act = do
235259 _ -> act ev >> return True
236260
237261resetTracer :: ProcessId -> Process ()
238−resetTracer pid = enableTrace pid
262+resetTracer pid = do
263+ say $ "resetting trace to " ++ (show pid)
264+ enableTrace pid
239265
240266-- | Stops a user supplied tracer started with 'startTracer'.
241267-- Note that only one tracer process can be active at any given time.
@@ -252,19 +278,17 @@ resetTracer pid = enableTrace pid
252278-- If tracing is support disabled for the node, this function will also
253279-- have no effect.
254280stopTracer :: Process ()
255−stopTracer = withLocalTracer $ \t ->
256− case t of
257− InactiveTracer -> return ()
258− (ActiveTracer _ _) -> withRegisteredTracer $ \pid -> do
259− -- we need to avoid killing the initial (base) tracer, as
260− -- nothing we rely on having exactly 1 registered tracer
261− -- process at all times!
262− basePid <- whereis "tracer.initial"
263− case basePid == (Just pid) of
264− True -> return ()
265− False -> send pid TraceEvDisable
281+stopTracer =
282+ withRegisteredTracer $ \pid -> do
283+ -- we need to avoid killing the initial (base) tracer, as
284+ -- nothing we rely on having exactly 1 registered tracer
285+ -- process at all times!
286+ basePid <- whereis "tracer.initial"
287+ case basePid == (Just pid) of
288+ True -> return ()
289+ False -> send pid TraceEvDisable
266290
267−withRegisteredTracer :: (ProcessId -> Process ()) -> Process ()
291+withRegisteredTracer :: (ProcessId -> Process a) -> Process a
268292withRegisteredTracer act = do
269293 currentTracer <- whereis "tracer"
270294 case currentTracer of
@@ -301,6 +325,12 @@ disableTrace :: Process ()
301325disableTrace =
302326 withLocalTracerSync $ \t sp -> Tracer.disableTraceSync t sp
303327
328+getTraceFlags :: Process TraceFlags
329+getTraceFlags = do
330+ (sp, rp) <- newChan
331+ withLocalTracer $ \t -> liftIO $ Tracer.getTraceFlags t sp
332+ receiveChan rp
333+
304334-- | Set the given flags for the current tracer.
305335setTraceFlagsAsync :: TraceFlags -> Process ()
306336setTraceFlagsAsync f = withLocalTracer $ \t -> liftIO $ Tracer.setTraceFlags t f