Skip to content

Commit 46ac63f

Browse files
committed
rework debugger communication framework to have separate sync and async channels
1 parent 972856f commit 46ac63f

File tree

6 files changed

+98
-94
lines changed

6 files changed

+98
-94
lines changed

external-stg-interpreter/app/ExtStgInterpreter.hs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{-# LANGUAGE LambdaCase, RecordWildCards #-}
22

33
import qualified Control.Concurrent.Chan.Unagi.Bounded as Unagi
4+
import Control.Concurrent.MVar
45

56
import Options.Applicative
67
import Data.Semigroup ((<>))
@@ -60,12 +61,18 @@ main = do
6061
{ dsKeepGCFacts = keepGCFacts
6162
}
6263

63-
(dbgCmdI, dbgCmdO) <- Unagi.newChan 100
64-
(dbgOutI, dbgOutO) <- Unagi.newChan 100
65-
let dbgChan = DebuggerChan (dbgCmdO, dbgOutI)
64+
(dbgAsyncI, dbgAsyncO) <- Unagi.newChan 100
65+
dbgRequestMVar <- newEmptyMVar
66+
dbgResponseMVar <- newEmptyMVar
67+
let dbgChan = DebuggerChan
68+
{ dbgSyncRequest = dbgRequestMVar
69+
, dbgSyncResponse = dbgResponseMVar
70+
, dbgAsyncEventIn = dbgAsyncI
71+
, dbgAsyncEventOut = dbgAsyncO
72+
}
6673

6774
case runDebugger of
68-
True -> debugProgram switchCWD appPath appArgs dbgChan dbgCmdI dbgOutO dbgScript debugSettings
75+
True -> debugProgram switchCWD appPath appArgs dbgChan dbgScript debugSettings
6976
False -> loadAndRunProgram isQuiet switchCWD appPath appArgs dbgChan DbgRunProgram doTracing debugSettings
7077

7178
dropRtsOpts :: [String] -> [String]

external-stg-interpreter/lib/Stg/Interpreter.hs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -397,10 +397,6 @@ contextSwitchTimer = do
397397

398398
evalStackMachine :: [Atom] -> M [Atom]
399399
evalStackMachine result = do
400-
(_, dbgOut) <- getDebuggerChan <$> gets ssDebuggerChan
401-
--liftIO $ Unagi.writeChan dbgOut $ DbgOutResult result
402-
--liftIO $ putStrLn $ "evalStackMachine resultIn = " ++ show result
403-
404400
stackPop >>= \case
405401
Nothing -> pure result
406402
Just stackCont -> do
@@ -861,9 +857,6 @@ runProgram isQuiet switchCWD progFilePath mods0 progArgs dbgChan dbgState tracin
861857
when (dbgState == DbgStepByStep) $ do
862858
Debugger.processCommandsUntilExit
863859

864-
let (dbgCmdO, _) = getDebuggerChan dbgChan
865-
nextDbgCmd <- NextDebugCommand <$> Unagi.tryReadChan dbgCmdO
866-
867860
tracingState <- case tracing of
868861
False -> pure NoTracing
869862
True -> do
@@ -887,7 +880,7 @@ runProgram isQuiet switchCWD progFilePath mods0 progArgs dbgChan dbgState tracin
887880
_ -> pure ()
888881
flip catch (\e -> do {freeResources; throw (e :: SomeException)}) $ do
889882
now <- getCurrentTime
890-
s@StgState{..} <- execStateT run (emptyStgState now isQuiet stateStore dl dbgChan nextDbgCmd dbgState tracingState debugSettings gcIn gcOut)
883+
s@StgState{..} <- execStateT run (emptyStgState now isQuiet stateStore dl dbgChan dbgState tracingState debugSettings gcIn gcOut)
891884
when switchCWD $ setCurrentDirectory currentDir
892885
freeResources
893886

external-stg-interpreter/lib/Stg/Interpreter/Base.hs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -221,17 +221,21 @@ newtype PrintableMVar a = PrintableMVar {unPrintableMVar :: MVar a} deriving Eq
221221
instance Show (PrintableMVar a) where
222222
show _ = "MVar"
223223

224-
newtype DebuggerChan = DebuggerChan {getDebuggerChan :: (OutChan DebugCommand, InChan DebugOutput)} deriving Eq
224+
data DebuggerChan
225+
= DebuggerChan
226+
{ dbgSyncRequest :: MVar DebugRequest
227+
, dbgSyncResponse :: MVar DebugResponse
228+
, dbgAsyncEventIn :: InChan DebugEvent
229+
, dbgAsyncEventOut :: OutChan DebugEvent
230+
}
231+
deriving Eq
232+
225233
instance Show DebuggerChan where
226234
show _ = "DebuggerChan"
227235

228-
newtype NextDebugCommand = NextDebugCommand (Element DebugCommand, IO DebugCommand)
229-
instance Show NextDebugCommand where
230-
show _ = "NextDebugCommand"
231-
instance Eq NextDebugCommand where
232-
_ == _ = True
233-
instance Ord NextDebugCommand where
234-
compare _ _ = EQ
236+
type DebugRequest = DebugCommand
237+
type DebugResponse = DebugOutput
238+
type DebugEvent = DebugOutput
235239

236240
data DebugCommand
237241
= CmdListClosures
@@ -252,6 +256,7 @@ data DebugOutput
252256
| DbgOutThreadReport !Int !ThreadState !Name !Addr String
253257
| DbgOutHeapObject !Addr !HeapObject
254258
| DbgOutResult ![Atom]
259+
| DbgOut
255260
deriving (Show)
256261

257262
data DebugState
@@ -402,7 +407,6 @@ data StgState
402407

403408
-- debugger API
404409
, ssDebuggerChan :: DebuggerChan
405-
, ssNextDebugCommand :: NextDebugCommand
406410

407411
, ssEvaluatedClosures :: !(Set Name)
408412
, ssBreakpoints :: !(Map Name Int)
@@ -440,21 +444,20 @@ data StgState
440444

441445
-- for the primop tests
442446
fakeStgStateForPrimopTests :: StgState
443-
fakeStgStateForPrimopTests = emptyStgState undefined undefined undefined undefined undefined undefined DbgRunProgram NoTracing defaultDebugSettings undefined undefined
447+
fakeStgStateForPrimopTests = emptyStgState undefined undefined undefined undefined undefined DbgRunProgram NoTracing defaultDebugSettings undefined undefined
444448

445449
emptyStgState :: UTCTime
446450
-> Bool
447451
-> PrintableMVar StgState
448452
-> DL
449453
-> DebuggerChan
450-
-> NextDebugCommand
451454
-> DebugState
452455
-> TracingState
453456
-> DebugSettings
454457
-> PrintableMVar ([Atom], StgState)
455458
-> PrintableMVar RefSet
456459
-> StgState
457-
emptyStgState now isQuiet stateStore dl dbgChan nextDbgCmd dbgState tracingState debugSettings gcIn gcOut = StgState
460+
emptyStgState now isQuiet stateStore dl dbgChan dbgState tracingState debugSettings gcIn gcOut = StgState
458461
{ ssHeap = mempty
459462
, ssStaticGlobalEnv = mempty
460463

@@ -537,7 +540,6 @@ emptyStgState now isQuiet stateStore dl dbgChan nextDbgCmd dbgState tracingState
537540

538541
-- debugger api
539542
, ssDebuggerChan = dbgChan
540-
, ssNextDebugCommand = nextDbgCmd
541543

542544
, ssEvaluatedClosures = Set.empty
543545
, ssBreakpoints = mempty

external-stg-interpreter/lib/Stg/Interpreter/Debugger.hs

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,50 +7,40 @@ import qualified Data.Set as Set
77
import qualified Data.Map as Map
88
import qualified Data.IntMap as IntMap
99
import qualified Control.Concurrent.Chan.Unagi.Bounded as Unagi
10+
import Control.Concurrent.MVar
1011

1112
import Stg.Interpreter.Base
1213
import Stg.Syntax
1314

1415
import Stg.Interpreter.Debugger.Internal
1516

16-
fetchNextDebugCommand :: M ()
17-
fetchNextDebugCommand = do
18-
(dbgCmd, _dbgOut) <- getDebuggerChan <$> gets ssDebuggerChan
19-
nextCmd <- liftIO $ Unagi.tryReadChan dbgCmd
20-
modify' $ \s@StgState{..} -> s {ssNextDebugCommand = NextDebugCommand nextCmd}
21-
2217
getNextDebugCommand :: M DebugCommand
2318
getNextDebugCommand = do
24-
NextDebugCommand (_, nextCmd) <- gets ssNextDebugCommand
25-
fetchNextDebugCommand
26-
liftIO nextCmd
19+
DebuggerChan{..} <- gets ssDebuggerChan
20+
liftIO $ takeMVar dbgSyncRequest
2721

2822
tryNextDebugCommand :: M (Maybe DebugCommand)
2923
tryNextDebugCommand = do
30-
NextDebugCommand (nextCmd, _) <- gets ssNextDebugCommand
31-
liftIO (Unagi.tryRead nextCmd) >>= \case
32-
Nothing -> pure Nothing
33-
c@Just{} -> do
34-
fetchNextDebugCommand
35-
pure c
24+
DebuggerChan{..} <- gets ssDebuggerChan
25+
liftIO (tryTakeMVar dbgSyncRequest)
3626

3727
runDebugCommand :: HasCallStack => DebugCommand -> M ()
3828
runDebugCommand cmd = do
3929
liftIO $ putStrLn $ "runDebugCommand: " ++ show cmd
40-
(_, dbgOut) <- getDebuggerChan <$> gets ssDebuggerChan
30+
DebuggerChan{..} <- gets ssDebuggerChan
4131
case cmd of
4232
CmdCurrentClosure -> do
4333
currentClosure <- gets ssCurrentClosure
4434
currentClosureAddr <- gets ssCurrentClosureAddr
4535
closureEnv <- gets ssCurrentClosureEnv
46-
liftIO $ Unagi.writeChan dbgOut $ DbgOutCurrentClosure currentClosure currentClosureAddr closureEnv
36+
liftIO $ putMVar dbgSyncResponse $ DbgOutCurrentClosure currentClosure currentClosureAddr closureEnv
4737

4838
CmdClearClosureList -> do
4939
modify' $ \s@StgState{..} -> s {ssEvaluatedClosures = Set.empty}
5040

5141
CmdListClosures -> do
5242
closures <- gets ssEvaluatedClosures
53-
liftIO $ Unagi.writeChan dbgOut $ DbgOutClosureList $ Set.toList closures
43+
liftIO $ putMVar dbgSyncResponse $ DbgOutClosureList $ Set.toList closures
5444

5545
CmdAddBreakpoint n i -> do
5646
modify' $ \s@StgState{..} -> s {ssBreakpoints = Map.insert n i ssBreakpoints}
@@ -67,7 +57,7 @@ runDebugCommand cmd = do
6757
heap <- gets ssHeap
6858
when (IntMap.member addr heap) $ do
6959
ho <- readHeap $ HeapPtr addr
70-
liftIO $ Unagi.writeChan dbgOut $ DbgOutHeapObject addr ho
60+
liftIO $ putMVar dbgSyncResponse $ DbgOutHeapObject addr ho
7161

7262
CmdStop -> do
7363
modify' $ \s@StgState{..} -> s {ssDebugState = DbgStepByStep}
@@ -112,7 +102,7 @@ checkBreakpoint breakpointName = do
112102
shouldStep <- hasFuel
113103
case dbgState of
114104
DbgStepByStep -> do
115-
reportState
105+
reportStateAsync
116106
unless exit processCommandsUntilExit
117107
DbgRunProgram -> do
118108
unless shouldStep $ modify' $ \s@StgState{..} -> s {ssDebugState = DbgStepByStep}
@@ -127,6 +117,6 @@ checkBreakpoint breakpointName = do
127117
| otherwise -> do
128118
-- HINT: trigger breakpoint
129119
liftIO $ putStrLn $ "hit breakpoint: " ++ show breakpointName
130-
reportState
120+
reportStateAsync
131121
modify' $ \s@StgState{..} -> s {ssDebugState = DbgStepByStep}
132122
unless exit processCommandsUntilExit

external-stg-interpreter/lib/Stg/Interpreter/Debugger/Internal.hs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import System.Console.Pretty
1515

1616
import qualified Control.Concurrent.Chan.Unagi.Bounded as Unagi
1717
import Control.Concurrent (myThreadId)
18+
import Control.Concurrent.MVar
1819

1920
import Stg.Interpreter.Base
2021
import Stg.Syntax
@@ -38,18 +39,28 @@ showOriginTrace i = do
3839
_ -> liftIO $ putStrLn str
3940
go i IntSet.empty
4041

41-
reportState :: M ()
42-
reportState = do
43-
(_, dbgOut) <- getDebuggerChan <$> gets ssDebuggerChan
42+
reportStateSync :: M ()
43+
reportStateSync = do
44+
DebuggerChan{..} <- gets ssDebuggerChan
45+
msg <- getThreadReport
46+
liftIO $ putMVar dbgSyncResponse msg
47+
48+
reportStateAsync :: M ()
49+
reportStateAsync = do
50+
DebuggerChan{..} <- gets ssDebuggerChan
51+
msg <- getThreadReport
52+
liftIO $ Unagi.writeChan dbgAsyncEventIn msg
53+
54+
getThreadReport :: M DebugOutput
55+
getThreadReport = do
4456
tid <- gets ssCurrentThreadId
4557
ts <- getThreadState tid
4658
currentClosure <- gets ssCurrentClosure >>= \case
4759
Nothing -> pure ""
4860
Just (Id c) -> pure $ binderUniqueName c
4961
currentClosureAddr <- gets ssCurrentClosureAddr
50-
liftIO $ do
51-
ntid <- myThreadId
52-
Unagi.writeChan dbgOut $ DbgOutThreadReport tid ts currentClosure currentClosureAddr (show ntid)
62+
ntid <- liftIO $ myThreadId
63+
pure $ DbgOutThreadReport tid ts currentClosure currentClosureAddr (show ntid)
5364

5465
showRetainer :: Int -> M ()
5566
showRetainer i = do
@@ -305,7 +316,7 @@ dbgCommands =
305316

306317
, ( ["get-current-thread-state"]
307318
, "reports the currently running thread state"
308-
, \_ -> reportState
319+
, \_ -> reportStateSync
309320
)
310321

311322
]

0 commit comments

Comments
 (0)