import select
+import string
import sys
import thread
import threading
import time
import os
import pty
+import Queue
class DbgTerminal:
+ #Reply cache from debugger
+ dbgreplyqueue = Queue.Queue()
+
+
def __init__ (self, binary, gdbReadCallback, childReadCallback):
#Set some members
def __connect( self ):
+ #This function handles readings from the debugger
+ def gdbCb(str):
+ self.gdbReadCallback(str)
+ self.dbgreplyqueue.put(str)
#Open pseudo-terminal where to-be-debugged process reads/writes to
self.ptymaster, self.ptyslave = pty.openpty()
self.childout = os.fdopen(self.ptymaster, "r", 0)
self.childin = os.fdopen(self.ptymaster, "w", 0)
- #Open the subprocess and get in- and out-streams
+ #Call gdb and get in- and out-streams to/from gdb
cmd = self.getCommand(self.binary)
self.gdbin, self.gdbout = os.popen4( cmd, bufsize=0)
-
#Set up a reading thread to gdb output
- self.gdbReadThread = self.ReadThread(self.gdbout, self.gdbReadCallback)
+ self.gdbReadThread = self.ReadThread(self.gdbout, gdbCb)
self.gdbReadThread.start()
- #Set up a reading thread to gdb output
+ #Set up a reading thread to childs output
self.childReadThread = self.ReadThread(self.childout, self.childReadCallback)
self.childReadThread.start()
#Set up tty gdb-childs process
- time.sleep(0.1)
self.sendSetTTY(os.ttyname(self.ptyslave))
- time.sleep(0.1)
-
+
- def getCommand( self, binary ):
- """Get the command to execute"""
+ def getDbgReply(self):
raise NotImplementedError()
def iseof( self ):
"""Check if terminal is closed already"""
-
return self.gdbReadThread.eventFin.isSet()
-
def stop( self ):
if not self.stopped:
self.childReadThread.eventFin.wait(1)
+ def getCommand( self, binary ):
+ """Get the command to execute"""
+ raise NotImplementedError()
+
def sendBreak(self, file, lineno):
raise NotImplementedError()
class GdbTerminal (DbgTerminal):
+ gdbreply = ""
+
+
def getCommand( self, binary ):
return "gdb --fullname %s" % (binary,)
self.gdbin.write("quit\n")
DbgTerminal.stop(self)
+ def getDbgReply(self, timeout=None):
+ while True:
+ splits = self.gdbreply.split("\n")
+
+ #Need more data: If there is a single (gdb) entry, then
+ #there are at least two splits
+ if len(splits) <= 1:
+ try:
+ self.gdbreply += self.dbgreplyqueue.get(True, timeout)
+ except Queue.Empty:
+ return None
+ #Yeah there is data!
+ else:
+ self.gdbreply = string.join(splits[1:], "(gdb)")
+ return string.strip(splits[0])
+
+ def flushDbgReply(self):
+
+ try:
+ self.gdbreply = ""
+ #Remove all elements from queue
+ while True:
+ self.dbgreplyqueue.get(False)
+ except Queue.Empty:
+ pass
if __name__ == "__main__":
term = GdbTerminal( "./main", tostdout, tostdout)
term.sendBreak("main.cpp", 13)
+ term.sendBreak("main.cpp", 14)
term.sendRun()
term.childin.write("1\n");
term.childin.write("2\n");
+
+ time.sleep(0.2)
+ term.flushDbgReply()
+ term.sendInspectVar("a+b")
+
+ term.sendContinue()
term.sendInspectVar("a+b")
term.sendContinue()
+ time.sleep(1)
+
+ print "reply >>>", term.getDbgReply(1)
+ print "reply >>>", term.getDbgReply(1)
+ print "reply >>>", term.getDbgReply(1)
+ print "reply >>>", term.getDbgReply(1)
+ print "reply >>>", term.getDbgReply(1)
+ print "reply >>>", term.getDbgReply(1)
+ print "reply >>>", term.getDbgReply(1)
+ print "reply >>>", term.getDbgReply(1)
+ print "reply >>>", term.getDbgReply(1)
+ print "reply >>>", term.getDbgReply(1)
+
+
while not term.iseof():
cmd = sys.stdin.readline()