15 def __init__ (self
, binary
, gdbReadCallback
, childReadCallback
):
18 self
.gdbReadCallback
= gdbReadCallback
19 self
.childReadCallback
= childReadCallback
23 #Connect to sub-process
26 def __connect( self
):
29 #Open pseudo-terminal where to-be-debugged process reads/writes to
30 self
.ptymaster
, self
.ptyslave
= pty
.openpty()
31 self
.childout
= os
.fdopen(self
.ptymaster
, "r", 0)
32 self
.childin
= os
.fdopen(self
.ptymaster
, "w", 0)
34 #Open the subprocess and get in- and out-streams
35 cmd
= self
.getCommand(self
.binary
)
36 self
.gdbin
, self
.gdbout
= os
.popen4( cmd
, bufsize
=0)
39 #Set up a reading thread to gdb output
40 self
.gdbReadThread
= self
.ReadThread(self
.gdbout
, self
.gdbReadCallback
)
41 self
.gdbReadThread
.start()
43 #Set up a reading thread to gdb output
44 self
.childReadThread
= self
.ReadThread(self
.childout
, self
.childReadCallback
)
45 self
.childReadThread
.start()
47 #Set up tty gdb-childs process
49 self
.sendSetTTY(os
.ttyname(self
.ptyslave
))
54 def getCommand( self
, binary
):
55 """Get the command to execute"""
56 raise NotImplementedError()
60 """Check if terminal is closed already"""
62 return self
.gdbReadThread
.eventFin
.isSet()
71 #Finish the reading-thread
72 self
.gdbReadThread
.fin
= True
73 self
.childReadThread
.fin
= True
74 self
.gdbReadThread
.eventFin
.wait(1)
75 self
.childReadThread
.eventFin
.wait(1)
78 def sendBreak(self
, file, lineno
):
79 raise NotImplementedError()
81 def sendContinue(self
):
82 raise NotImplementedError()
85 raise NotImplementedError()
87 def sendInspectVar(self
, var
):
88 raise NotImplementedError()
90 def sendInspectExpr(self
, expr
):
91 raise NotImplementedError()
93 def sendSetTTY(self
, ttyname
):
94 raise NotImplementedError()
97 raise NotImplementedError()
100 class ReadThread (threading
.Thread
):
101 """Thread which reads from sub-process output"""
103 def __init__( self
, stream
, callback
, sleep
=0.1):
106 self
.callback
= callback
108 self
.eventFin
= threading
.Event()
109 threading
.Thread
.__init
__(self
)
115 #Wait until data is available
116 rlist
, wlist
, xlist
= select
.select([self
.stream
], [], [], self
.sleep
)
118 #If we should finish, finish
131 #Set the finished event
137 class GdbTerminal (DbgTerminal
):
139 def getCommand( self
, binary
):
140 return "gdb --fullname %s" % (binary
,)
142 def sendBreak(self
, file, lineno
):
143 self
.gdbin
.write("break %s:%d\n" % (file, lineno
))
145 def sendContinue(self
):
146 self
.gdbin
.write("cont\n")
149 self
.gdbin
.write("run\n")
151 def sendInspectVar(self
, var
):
152 self
.sendInspectExpr(var
)
154 def sendInspectExpr(self
, expr
):
155 self
.gdbin
.write("print %s\n" % (expr
,))
157 def sendSetTTY(self
, ttyname
):
158 self
.gdbin
.write("set inferior-tty %s\n" % (ttyname
,))
161 self
.gdbin
.write("quit\n")
162 DbgTerminal
.stop(self
)
166 if __name__
== "__main__":
169 sys
.stdout
.write(str)
174 term
= GdbTerminal( "./main", tostdout
, tostdout
)
175 term
.sendBreak("main.cpp", 13)
177 term
.childin
.write("1\n");
178 term
.childin
.write("2\n");
179 term
.sendInspectVar("a+b")
183 while not term
.iseof():
185 cmd
= sys
.stdin
.readline()
193 term
.gdbin
.write(cmd
)