Use special PTY for inferior input/output...
authorJan Vrany <jan.vrany@fit.cvut.cz>
Mon, 09 Jun 2014 10:28:46 +0100
changeset 10 f04a22c9b16c
parent 9 5cc8797f6523
child 11 474fbb650afe
Use special PTY for inferior input/output... ...so gdb control streams are not interleaved with inferior's input/output.
GDB.st
GDBDriver.st
GDBLauncher.st
GDBStatusEvent.st
libgdbs.rc
--- a/GDB.st	Wed Jun 04 09:37:08 2014 +0100
+++ b/GDB.st	Mon Jun 09 10:28:46 2014 +0100
@@ -24,6 +24,26 @@
     "Created: / 02-06-2014 / 23:06:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
+inferiorStderr
+    ^ driver inferiorOutput
+
+    "Created: / 09-06-2014 / 10:01:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+inferiorStdin
+    ^ driver inferiorInput
+
+    "Created: / 09-06-2014 / 10:00:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+inferiorStdout
+    ^ driver inferiorOutput
+
+    "Created: / 09-06-2014 / 10:01:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!GDB methodsFor:'accessing-private'!
+
 nextCommandSequnceNumber
     commandSequenceNumber := commandSequenceNumber + 1.
     commandSequenceNumber == SmallInteger maxVal ifTrue:[ 
--- a/GDBDriver.st	Wed Jun 04 09:37:08 2014 +0100
+++ b/GDBDriver.st	Mon Jun 09 10:28:46 2014 +0100
@@ -1,8 +1,9 @@
 "{ Package: 'jv:libgdbs' }"
 
 Object subclass:#GDBDriver
-	instanceVariableNames:'pid input output eventAnnouncer eventQueue eventQueueLock
-		eventQueueNotifier eventDispatchProcess eventPumpProcess'
+	instanceVariableNames:'pid debuggerInput debuggerOutput inferiorInput inferiorOutput
+		eventAnnouncer eventQueue eventQueueLock eventQueueNotifier
+		eventDispatchProcess eventPumpProcess'
 	classVariableNames:''
 	poolDictionaries:'GDBDebugFlags'
 	category:'GDB-Private'
@@ -11,19 +12,30 @@
 
 !GDBDriver class methodsFor:'instance creation'!
 
-pid:pidArg input:inputArg output:outputArg
+debuggerPid:pidArg debuggerInput:inputArg debuggerOutput:outputArg inferiorInput:inferiorInputArg inferiorOutput:inferiorOutputArg 
     ^ self new 
-            initializeWithPid:pidArg
-            input:inputArg
-            output:outputArg
+        initializeWithDebuggerPid:pidArg
+        debuggerInput:inputArg
+        debuggerOutput:outputArg
+        inferiorInput:inferiorInputArg
+        inferiorOutput:inferiorOutputArg
 
     "Created: / 26-05-2014 / 13:35:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 09-06-2014 / 09:20:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !GDBDriver methodsFor:'accessing'!
 
 eventAnnouncer
     ^ eventAnnouncer
+!
+
+inferiorInput
+    ^ inferiorInput
+!
+
+inferiorOutput
+    ^ inferiorOutput
 ! !
 
 !GDBDriver methodsFor:'event dispatching'!
@@ -115,9 +127,9 @@
 
     command := aGDBCommandEvent command.
     command token notNil ifTrue:[ 
-        input nextPutAll: command token printString.
+        debuggerInput nextPutAll: command token printString.
     ].
-    input nextPutLine: command asString.
+    debuggerInput nextPutLine: command asString.
 
     "Created: / 02-06-2014 / 23:38:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
@@ -127,8 +139,8 @@
 eventPumpLoop
     | parser |
 
-    parser := GDBParser on: output.
-    [ output atEnd ] whileFalse:[ 
+    parser := GDBParser on: debuggerOutput.
+    [ debuggerOutput atEnd ] whileFalse:[ 
         | eventset |
 
         [
@@ -143,16 +155,16 @@
 
             terminator := '(gdb)'.
             i := 1.
-            output notNil ifTrue:[
-                [ output atEnd not and: [i <= terminator size ] ] whileTrue:[ 
-                    c := output next.
+            debuggerOutput notNil ifTrue:[
+                [ debuggerOutput atEnd not and: [i <= terminator size ] ] whileTrue:[ 
+                    c := debuggerOutput next.
                     c == (terminator at: i) ifTrue:[ 
                         i := i + 1.
                     ] ifFalse:[ 
                         i := 1.
                     ].
                 ].
-                output next. "/ read nl.
+                debuggerOutput next. "/ read nl.
             ] ifFalse:[ 
                 ^ self.
             ].
@@ -222,20 +234,23 @@
 
 !GDBDriver methodsFor:'initialize & release'!
 
-initializeWithPid:pidArg input:inputArg output:outputArg 
+initializeWithDebuggerPid:pidArg debuggerInput:inputArg debuggerOutput:outputArg inferiorInput:inferiorInputArg inferiorOutput:inferiorOutputArg 
     pid := pidArg.
-    input := inputArg.
-
-    output := outputArg.
+    debuggerInput := inputArg.
+    debuggerOutput := outputArg.
+    inferiorInput := inferiorInputArg.
+    inferiorOutput := inferiorOutputArg.
     eventQueue := OrderedCollection new.
     eventQueueLock := RecursionLock new.
     eventQueueNotifier := Semaphore new.
     eventAnnouncer := Announcer new.
-
-    eventAnnouncer when: GDBCommandEvent send: #onCommand: to: self.
+    eventAnnouncer 
+        when:GDBCommandEvent
+        send:#onCommand:
+        to:self.
 
     "Created: / 26-05-2014 / 13:35:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 02-06-2014 / 23:39:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 09-06-2014 / 09:14:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 release
@@ -262,13 +277,13 @@
     ].
     pid := nil.       
     eventQueueNotifier signalForAll.           
-    input notNil ifTrue:[ 
-        input close.
-        input := nil.
+    debuggerInput notNil ifTrue:[ 
+        debuggerInput close.
+        debuggerInput := nil.
     ].
-    output notNil ifTrue:[ 
-        output close.
-        output := nil.
+    debuggerOutput notNil ifTrue:[ 
+        debuggerOutput close.
+        debuggerOutput := nil.
     ].
 
     "Created: / 26-05-2014 / 21:31:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
--- a/GDBLauncher.st	Wed Jun 04 09:37:08 2014 +0100
+++ b/GDBLauncher.st	Mon Jun 09 10:28:46 2014 +0100
@@ -11,43 +11,76 @@
 !GDBLauncher class methodsFor:'starting'!
 
 startGDB
-    | inputPipe input outputPipe output args controller pid |
+    | inputPipe input outputPipe output  args  controller pid inferiorOutput inferiorInput ptyTriple ptyName master slave|
+
+    OperatingSystem isUNIXlike ifTrue:[ 
+        "Use a pseudo-tty"
+        ptyTriple := OperatingSystem makePTY.
+
+        ptyName := ptyTriple at:3.
+
+        "/ pty at:1 is the master;
+        "/ pty at:2 is the slave
+        master := NonPositionableExternalStream forReadWriteToFileDescriptor:(ptyTriple at:1).
+        master buffered:false.
+
+        slave := NonPositionableExternalStream forReadWriteToFileDescriptor:(ptyTriple at:2).
+        slave close.
+
+        inferiorInput := inferiorOutput := master.
+    ] ifFalse:[ 
+        OperatingSystem isMSWINDOWSNTlike ifTrue:[ 
+            self error: 'Windows are not (yet) supported'
+        ] ifFalse:[ 
+            self error: 'Operating system not supported'
+        ]
+    ].
+
+
 
     inputPipe := NonPositionableExternalStream makePipe.
     input := inputPipe second.
-
     outputPipe := NonPositionableExternalStream makePipe.
-    output := outputPipe first. 
-
-    args := #('/usr/bin/gdb' '--interpreter' 'mi2').
-
-    Processor monitor:[
-        pid := OperatingSystem exec: args first withArguments:args
-            environment: OperatingSystem getEnvironment
-            fileDescriptors:{inputPipe first fileDescriptor . outputPipe second fileDescriptor . outputPipe second fileDescriptor}
-            fork:true
-            newPgrp:false
-            inDirectory:Filename currentDirectory.
-        controller := GDBDriver pid: pid input: input output: output. 
-        pid.
-    ] action:[:stat |
-        controller released: stat.
+    output := outputPipe first.
+    args := #( '/usr/bin/gdb' '--interpreter' 'mi2' ).
+    ptyName notNil ifTrue:[ 
+        args := args , { '-tty=', ptyName }.
     ].
-
+    Processor 
+        monitor:[
+            pid := OperatingSystem 
+                    exec:args first
+                    withArguments:args
+                    environment:OperatingSystem getEnvironment
+                    fileDescriptors:{
+                            inputPipe first fileDescriptor.
+                            outputPipe second fileDescriptor.
+                            outputPipe second fileDescriptor
+                        }
+                    fork:true
+                    newPgrp:false
+                    inDirectory:Filename currentDirectory.
+            controller := GDBDriver 
+                    debuggerPid:pid
+                    debuggerInput:input
+                    debuggerOutput:output
+                    inferiorInput:inferiorInput
+                    inferiorOutput:inferiorOutput.
+            pid.
+        ]
+        action:[:stat | controller released:stat. ].
     inputPipe first close.
     outputPipe second close.
-
-    pid isNil ifTrue:[ 
+    pid isNil ifTrue:[
         input close.
         output close.
-        self error: 'Failed to launch gdb'.
+        self error:'Failed to launch gdb'.
         ^ self.
     ].
-
     ^ controller
 
     "Created: / 26-05-2014 / 21:18:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 02-06-2014 / 23:04:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 09-06-2014 / 09:48:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !GDBLauncher class methodsFor:'documentation'!
--- a/GDBStatusEvent.st	Wed Jun 04 09:37:08 2014 +0100
+++ b/GDBStatusEvent.st	Mon Jun 09 10:28:46 2014 +0100
@@ -7,6 +7,7 @@
 	category:'GDB-Core-Events'
 !
 
+
 !GDBStatusEvent methodsFor:'testing'!
 
 isStatusEvent
@@ -15,3 +16,10 @@
     "Created: / 01-06-2014 / 23:38:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!GDBStatusEvent class methodsFor:'documentation'!
+
+version_HG
+
+    ^ '$Changeset: <not expanded> $'
+! !
+
--- a/libgdbs.rc	Wed Jun 04 09:37:08 2014 +0100
+++ b/libgdbs.rc	Mon Jun 09 10:28:46 2014 +0100
@@ -25,7 +25,7 @@
       VALUE "LegalCopyright", "My CopyRight or CopyLeft\0"
       VALUE "ProductName", "LibraryName\0"
       VALUE "ProductVersion", "6.2.4.0\0"
-      VALUE "ProductDate", "Wed, 04 Jun 2014 08:34:53 GMT\0"
+      VALUE "ProductDate", "Mon, 09 Jun 2014 09:26:44 GMT\0"
     END
 
   END