17 #Reply cache from debugger
18 dbgreplyqueue
= Queue
.Queue()
21 def __init__ (self
, binary
, gdbReadCallback
, childReadCallback
):
24 self
.gdbReadCallback
= gdbReadCallback
25 self
.childReadCallback
= childReadCallback
29 #Connect to sub-process
32 def __connect( self
):
34 #This function handles readings from the debugger
36 self
.gdbReadCallback(str)
37 self
.dbgreplyqueue
.put(str)
39 #Open pseudo-terminal where to-be-debugged process reads/writes to
40 self
.ptymaster
, self
.ptyslave
= pty
.openpty()
41 self
.childout
= os
.fdopen(self
.ptymaster
, "r", 0)
42 self
.childin
= os
.fdopen(self
.ptymaster
, "w", 0)
44 #Call gdb and get in- and out-streams to/from gdb
45 cmd
= self
.getCommand(self
.binary
)
46 self
.gdbin
, self
.gdbout
= os
.popen4( cmd
, bufsize
=0)
48 #Set up a reading thread to gdb output
49 self
.gdbReadThread
= self
.ReadThread(self
.gdbout
, gdbCb
)
50 self
.gdbReadThread
.start()
52 #Set up a reading thread to childs output
53 self
.childReadThread
= self
.ReadThread(self
.childout
, self
.childReadCallback
)
54 self
.childReadThread
.start()
56 #Set up tty gdb-childs process
57 self
.sendSetTTY(os
.ttyname(self
.ptyslave
))
61 def getDbgReply(self
):
62 raise NotImplementedError()
66 """Check if terminal is closed already"""
67 return self
.gdbReadThread
.eventFin
.isSet()
75 #Finish the reading-thread
76 self
.gdbReadThread
.fin
= True
77 self
.childReadThread
.fin
= True
78 self
.gdbReadThread
.eventFin
.wait(1)
79 self
.childReadThread
.eventFin
.wait(1)
82 def getCommand( self
, binary
):
83 """Get the command to execute"""
84 raise NotImplementedError()
86 def sendBreak(self
, file, lineno
):
87 raise NotImplementedError()
89 def sendContinue(self
):
90 raise NotImplementedError()
93 raise NotImplementedError()
95 def sendInspectVar(self
, var
):
96 raise NotImplementedError()
98 def sendInspectExpr(self
, expr
):
99 raise NotImplementedError()
101 def sendSetTTY(self
, ttyname
):
102 raise NotImplementedError()
105 raise NotImplementedError()
108 class ReadThread (threading
.Thread
):
109 """Thread which reads from sub-process output"""
111 def __init__( self
, stream
, callback
, sleep
=0.1):
114 self
.callback
= callback
116 self
.eventFin
= threading
.Event()
117 threading
.Thread
.__init
__(self
)
123 #Wait until data is available
124 rlist
, wlist
, xlist
= select
.select([self
.stream
], [], [], self
.sleep
)
126 #If we should finish, finish
139 #Set the finished event
145 class GdbTerminal (DbgTerminal
):
150 def getCommand( self
, binary
):
151 return "gdb --fullname %s" % (binary
,)
153 def sendBreak(self
, file, lineno
):
154 self
.gdbin
.write("break %s:%d\n" % (file, lineno
))
156 def sendContinue(self
):
157 self
.gdbin
.write("cont\n")
160 self
.gdbin
.write("run\n")
162 def sendInspectVar(self
, var
):
163 self
.sendInspectExpr(var
)
165 def sendInspectExpr(self
, expr
):
166 self
.gdbin
.write("print %s\n" % (expr
,))
168 def sendSetTTY(self
, ttyname
):
169 self
.gdbin
.write("set inferior-tty %s\n" % (ttyname
,))
172 self
.gdbin
.write("quit\n")
173 DbgTerminal
.stop(self
)
175 def getDbgReply(self
, timeout
=None):
178 splits
= self
.gdbreply
.split("\n")
180 #Need more data: If there is a single (gdb) entry, then
181 #there are at least two splits
184 self
.gdbreply
+= self
.dbgreplyqueue
.get(True, timeout
)
189 self
.gdbreply
= string
.join(splits
[1:], "(gdb)")
190 return string
.strip(splits
[0])
192 def flushDbgReply(self
):
196 #Remove all elements from queue
198 self
.dbgreplyqueue
.get(False)
202 if __name__
== "__main__":
205 sys
.stdout
.write(str)
210 term
= GdbTerminal( "./main", tostdout
, tostdout
)
211 term
.sendBreak("main.cpp", 13)
212 term
.sendBreak("main.cpp", 14)
214 term
.childin
.write("1\n");
215 term
.childin
.write("2\n");
219 term
.sendInspectVar("a+b")
222 term
.sendInspectVar("a+b")
228 print "reply >>>", term
.getDbgReply(1)
229 print "reply >>>", term
.getDbgReply(1)
230 print "reply >>>", term
.getDbgReply(1)
231 print "reply >>>", term
.getDbgReply(1)
232 print "reply >>>", term
.getDbgReply(1)
233 print "reply >>>", term
.getDbgReply(1)
234 print "reply >>>", term
.getDbgReply(1)
235 print "reply >>>", term
.getDbgReply(1)
236 print "reply >>>", term
.getDbgReply(1)
237 print "reply >>>", term
.getDbgReply(1)
240 while not term
.iseof():
242 cmd
= sys
.stdin
.readline()
250 term
.gdbin
.write(cmd
)