Fix: initialize debugger features early during initialization
authorJan Vrany <jan.vrany@fit.cvut.cz>
Tue, 27 Mar 2018 08:55:29 +0100
changeset 116 ffd185f7a357
parent 115 efb49f057011
child 117 17e5e955c3c1
Fix: initialize debugger features early during initialization The frontend or `stx:libgdbs` may need to query features to conditionally perform some logic, however, if the target does not support async mode (such as Windows), it would block. The GDB documentation says: Whenever a target can change, due to commands such as -target-select, -target-attach or -exec-run, the list of target features may change, and the frontend should obtain it again. The problem is, however, that on a target that does not support, once `-exec-run` is issued, the inferior runs so GDB does not accept any commands until inferior stops. To workaround this until a better solution is found, initialize target features on first stopped event and until initialized, use "default natives features", a hard-coded set. Ugly, but we should move on.
GDBConnection.st
GDBDebugger.st
GDBProcess.st
GDBUnixProcess.st
GDBWindowsProcess.st
--- a/GDBConnection.st	Tue Mar 27 08:50:56 2018 +0100
+++ b/GDBConnection.st	Tue Mar 27 08:55:29 2018 +0100
@@ -94,6 +94,12 @@
     ^ inferiorPTY
 !
 
+nativeTargetFeatures
+    ^ process nativeTargetFeatures
+
+    "Created: / 09-04-2018 / 15:40:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
 recorder
     ^ recorder
 !
--- a/GDBDebugger.st	Tue Mar 27 08:50:56 2018 +0100
+++ b/GDBDebugger.st	Tue Mar 27 08:55:29 2018 +0100
@@ -120,23 +120,11 @@
             * https://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Support-Commands.html,
               command `-list-features`
     "
-
-    debuggerFeatures isNil ifTrue:[ 
-        | result |
-
-        result := self send: GDBMI_list_features new.
-        debuggerFeatures := result propertyAt: #features.
-    ].
-    targetFeatures isNil ifTrue:[
-        | result |
-
-        result := self send: GDBMI_list_target_features new.
-        targetFeatures := result propertyAt: #features.
-    ].
-    ^ debuggerFeatures , targetFeatures
+    ^ debuggerFeatures , (targetFeatures ? connection nativeTargetFeatures)
 
     "Created: / 07-02-2018 / 10:50:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 07-02-2018 / 12:46:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 26-03-2018 / 21:35:22 / jv"
+    "Modified: / 09-04-2018 / 15:39:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 inferiorForId: id
@@ -281,12 +269,14 @@
         cmd isString ifTrue:[
             cmd := GDBCLICommand new value:cmd.
         ].    
+        cmd token: self nextCommandSequnceNumber.
         connection pushEvent:(GDBCommandEvent new command:cmd).
         nil.
     ]
 
     "Created: / 02-06-2014 / 23:45:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
     "Modified: / 04-02-2018 / 00:21:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 26-03-2018 / 21:19:59 / jv"
 !
 
 send:command andWaitFor:eventHandlers
@@ -382,8 +372,6 @@
     ].
     token := self nextCommandSequnceNumber.
     cmd token:token.
-    self assert:Processor activeProcess ~~ connection eventDispatchProcess
-        message:'Cannot send commands from within event dispatching process. Would deadlock'.                
     handler1 := [:ev | 
         ev token == token ifTrue:[
             connection eventAnnouncer unsubscribe:handler1.
@@ -402,6 +390,7 @@
 
     "Created: / 26-01-2018 / 21:47:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
     "Modified (format): / 04-02-2018 / 00:20:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 26-03-2018 / 21:48:02 / jv"
 ! !
 
 !GDBDebugger methodsFor:'commands - API'!
@@ -751,8 +740,14 @@
         thread onStoppedEvent: aGDBStoppedEvent.
     ].
 
+    "/ Initialize target features properly
+    targetFeatures isNil ifTrue:[
+        self send: GDBMI_list_target_features new 
+             andWithResultDo:[ :result | targetFeatures := result propertyAt: #features ].
+    ].
+
     "Created: / 07-09-2014 / 23:34:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 12-07-2017 / 13:47:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 09-04-2018 / 15:42:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 onThreadCreatedEvent:aGDBThreadCreatedEvent 
@@ -771,8 +766,11 @@
     inferior := self inferiorForId:aGDBThreadExitedEvent threadGroupId.
     inferior onThreadExitedEvent:aGDBThreadExitedEvent.
 
+    "/ reset target features
+    targetFeatures := nil.
+
     "Created: / 07-09-2014 / 21:20:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 18-03-2015 / 13:57:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 09-04-2018 / 15:42:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 onThreadGroupAddedEvent:aGDBThreadGroupAddedEvent 
@@ -784,9 +782,10 @@
     inferior := GDBThreadGroup newWithDebugger:self
             id:aGDBThreadGroupAddedEvent threadGroupId.
     inferiors add:inferior.
-    aGDBThreadGroupAddedEvent setThreadGroup:inferior
+    aGDBThreadGroupAddedEvent setThreadGroup:inferior.
 
-    "Modified: / 07-09-2014 / 21:18:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 26-03-2018 / 21:46:51 / jv"
+    "Modified: / 09-04-2018 / 15:36:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 onThreadGroupExitedEvent:aGDBThreadGroupExitedEvent 
@@ -807,13 +806,10 @@
     inferior := self inferiorForId:aGDBThreadGroupStartedEvent threadGroupId.
     inferior setPid:aGDBThreadGroupStartedEvent pid.
     aGDBThreadGroupStartedEvent setThreadGroup:inferior.
-    "/ Also, we have to reset targetFeatures since we get no notification
-    "/ that the target has changed. Note, that `targetFeatures` are lazily 
-    "/ initialized in #features.
-    targetFeatures := nil
 
     "Created: / 06-09-2014 / 02:37:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
     "Modified (comment): / 07-02-2018 / 12:50:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 26-03-2018 / 21:33:11 / jv"
 ! !
 
 !GDBDebugger methodsFor:'finalization'!
@@ -827,6 +823,8 @@
 !GDBDebugger methodsFor:'initialize & release'!
 
 initializeWithProcess: aGDBProcess
+    | result |
+
     self registerForFinalization.
 
     finalizationRegistry := Registry new.
@@ -846,12 +844,16 @@
     ].
     self send: (GDBMI_gdb_set arguments: #('target-async' 'on')).
 
+    result := self send: GDBMI_list_features new.
+    debuggerFeatures := result propertyAt: #features.
+    targetFeatures := nil.
+
     prettyPrintingEnabled := false.
     frameFiltersEnabled := false.
 
     "Created: / 20-06-2014 / 21:45:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 12-01-2018 / 00:13:09 / jv"
-    "Modified: / 28-01-2018 / 23:19:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 26-03-2018 / 21:36:31 / jv"
+    "Modified: / 09-04-2018 / 15:38:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 release
@@ -921,6 +923,19 @@
 
     "Created: / 07-02-2018 / 11:32:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
     "Modified (comment): / 07-02-2018 / 12:44:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+hasFeatureAsync
+    "Indicates that the target is capable of asynchronous command execution, which means 
+     that GDB will accept further commands while the target is running." 
+
+    targetFeatures notNil ifTrue:[ 
+        ^ targetFeatures includes: 'async'
+    ] ifFalse:[ 
+        ^ connection nativeTargetFeatures includes: 'async'.
+    ].
+
+    "Created: / 09-04-2018 / 15:45:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !GDBDebugger methodsFor:'testing'!
--- a/GDBProcess.st	Tue Mar 27 08:50:56 2018 +0100
+++ b/GDBProcess.st	Tue Mar 27 08:55:29 2018 +0100
@@ -125,6 +125,12 @@
     "Modified: / 15-12-2017 / 23:58:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
+nativeTargetFeatures
+    ^ self subclassResponsibility
+
+    "Created: / 09-04-2018 / 15:40:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
 pid
     ^ pid
 ! !
--- a/GDBUnixProcess.st	Tue Mar 27 08:50:56 2018 +0100
+++ b/GDBUnixProcess.st	Tue Mar 27 08:55:29 2018 +0100
@@ -62,6 +62,12 @@
     ^ consolePTY master
 
     "Created: / 02-06-2017 / 23:36:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+nativeTargetFeatures
+    ^ #('async')
+
+    "Created: / 09-04-2018 / 15:40:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !GDBUnixProcess methodsFor:'initialization & release'!
--- a/GDBWindowsProcess.st	Tue Mar 27 08:50:56 2018 +0100
+++ b/GDBWindowsProcess.st	Tue Mar 27 08:55:29 2018 +0100
@@ -50,6 +50,14 @@
 "
 ! !
 
+!GDBWindowsProcess methodsFor:'accessing'!
+
+nativeTargetFeatures
+    ^ #()
+
+    "Created: / 09-04-2018 / 15:41:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
 !GDBWindowsProcess methodsFor:'error pump'!
 
 errorPumpLoop