src/eric7/RemoteServer/EricServerDebuggerRequestHandler.py

branch
server
changeset 10561
be23a662d709
parent 10555
08e853c0c77b
child 10563
b4b47c1a02ba
equal deleted inserted replaced
10560:28b14d2df6a1 10561:be23a662d709
14 import subprocess 14 import subprocess
15 import sys 15 import sys
16 import types 16 import types
17 17
18 from .EricRequestCategory import EricRequestCategory 18 from .EricRequestCategory import EricRequestCategory
19
19 20
20 class EricServerDebuggerRequestHandler: 21 class EricServerDebuggerRequestHandler:
21 """ 22 """
22 Class implementing the debugger request handler of the eric-ide server. 23 Class implementing the debugger request handler of the eric-ide server.
23 """ 24 """
130 if data is None: 131 if data is None:
131 # socket was closed by debug client 132 # socket was closed by debug client
132 self.__clientSocketDisconnected(sock) 133 self.__clientSocketDisconnected(sock)
133 elif data: 134 elif data:
134 method = data["method"] 135 method = data["method"]
136
137 # 1. process debug client messages before relaying
135 if method == "DebuggerId" and sock in self.__pendingConnections: 138 if method == "DebuggerId" and sock in self.__pendingConnections:
136 debuggerId = data['params']['debuggerId'] 139 debuggerId = data['params']['debuggerId']
137 self.__connections[debuggerId] = sock 140 self.__connections[debuggerId] = sock
138 self.__pendingConnections.remove(sock) 141 self.__pendingConnections.remove(sock)
139 if self.__mainClientId is None: 142 if self.__mainClientId is None:
141 144
142 elif method == "ResponseBanner": 145 elif method == "ResponseBanner":
143 # add an indicator for the eric-ide server 146 # add an indicator for the eric-ide server
144 data["params"]["platform"] += " (eric-ide Server)" 147 data["params"]["platform"] += " (eric-ide Server)"
145 148
146 # pass on the data to the eric-ide 149 # 2. pass on the data to the eric-ide
147 jsonStr = json.dumps(data) 150 jsonStr = json.dumps(data)
148 print("Client Response:", jsonStr) 151 print("Client Response:", jsonStr)
149 self.__server.sendJson( 152 self.__server.sendJson(
150 category=EricRequestCategory.Debugger, 153 category=EricRequestCategory.Debugger,
151 reply="DebugClientResponse", 154 reply="DebugClientResponse",
152 params={"response": jsonStr}, 155 params={"response": jsonStr},
153 ) 156 )
157
158 # 3. process debug client messages after relaying
159 if method == "ResponseExit":
160 for sock in list(self.__connections.values()):
161 if not self.__server.isSocketClosed(sock):
162 self.__clientSocketDisconnected(sock)
154 163
155 def __clientSocketDisconnected(self, sock): 164 def __clientSocketDisconnected(self, sock):
156 """ 165 """
157 Private slot handling a socket disconnecting. 166 Private method handling a socket disconnecting.
158 167
159 @param sock reference to the disconnected socket 168 @param sock reference to the disconnected socket
160 @type QTcpSocket 169 @type socket.socket
161 """ 170 """
162 self.__server.getSelector().unregister(sock) 171 self.__server.getSelector().unregister(sock)
163 172
164 for debuggerId in list(self.__connections): 173 for debuggerId in list(self.__connections):
165 if self.__connections[debuggerId] is sock: 174 if self.__connections[debuggerId] is sock:
176 break 185 break
177 else: 186 else:
178 if sock in self.__pendingConnections: 187 if sock in self.__pendingConnections:
179 self.__pendingConnections.remove(sock) 188 self.__pendingConnections.remove(sock)
180 189
181 sock.shutdown(socket.SHUT_RDWR)
182 sock.close() 190 sock.close()
183 191
184 if not self.__connections: 192 if not self.__connections:
185 # no active connections anymore 193 # no active connections anymore
186 self.__server.sendJson( 194 self.__server.sendJson(
187 category=EricRequestCategory.Debugger, 195 category=EricRequestCategory.Debugger,
188 reply="LastDebugClientExited", 196 reply="LastDebugClientExited",
189 params={}, 197 params={},
190 ) 198 )
199
200 def __mainClientExited(self):
201 """
202 Private method to handle exiting of the main debug client.
203 """
204 self.__server.sendJson(
205 category=EricRequestCategory.Debugger,
206 reply="MainClientExited",
207 params={"debugger_id": self.__mainClientId if self.__mainClientId else ""},
208 )
191 209
192 def __serviceDbgClientStdoutStderr(self, key): 210 def __serviceDbgClientStdoutStderr(self, key):
193 """ 211 """
194 Private method to service the debug client stdout and stderr channels. 212 Private method to service the debug client stdout and stderr channels.
195 213
236 params={}, 254 params={},
237 ) 255 )
238 256
239 def __shutdownSocket(self, debuggerId, sock): 257 def __shutdownSocket(self, debuggerId, sock):
240 """ 258 """
241 Private slot to shut down a socket. 259 Private method to shut down a socket.
242 260
243 @param debuggerId ID of the debugger the socket belongs to 261 @param debuggerId ID of the debugger the socket belongs to
244 @type str 262 @type str
245 @param sock reference to the socket 263 @param sock reference to the socket
246 @type socket.socket 264 @type socket.socket
307 self.__client = subprocess.Popen( 325 self.__client = subprocess.Popen(
308 args, stdout=subprocess.PIPE, stderr=subprocess.PIPE 326 args, stdout=subprocess.PIPE, stderr=subprocess.PIPE
309 ) 327 )
310 # TODO: register stdin & stderr with selector 328 # TODO: register stdin & stderr with selector
311 329
312 def __stopClient(self, params): 330 def __stopClient(self, params): # noqa: U100
313 """ 331 """
314 Private method to stop the current debug client process. 332 Private method to stop the current debug client process.
315 333
316 @param params dictionary containing the request data 334 @param params dictionary containing the request data
317 @type dict 335 @type dict
331 """ 349 """
332 debuggerId = params["debugger_id"] 350 debuggerId = params["debugger_id"]
333 jsonStr = params["command"] 351 jsonStr = params["command"]
334 print(debuggerId, "->", jsonStr) 352 print(debuggerId, "->", jsonStr)
335 353
336 if not debuggerId and self.__mainClientId: 354 if not debuggerId and self.__mainClientId and "RequestBanner" in jsonStr:
355 # modify the target for the 'RequestBanner' request
337 debuggerId = self.__mainClientId 356 debuggerId = self.__mainClientId
338 357
339 try: 358 if debuggerId == "<<all>>":
340 sock = self.__connections[debuggerId] 359 # broadcast to all connected debug clients
341 except KeyError: 360 for sock in self.__connections.values():
342 print(f"Command for unknown debugger ID '{debuggerId}' received.") 361 self.__server.sendJsonCommand(jsonStr, sock)
343 # tell the eric-ide again, that this debugger ID is gone 362 else:
344 self.__server.sendJson( 363 try:
345 category=EricRequestCategory.Debugger, 364 sock = self.__connections[debuggerId]
346 reply="DebugClientDisconnected", 365 self.__server.sendJsonCommand(jsonStr, sock)
347 params={"debugger_id": debuggerId}, 366 except KeyError:
348 ) 367 print(f"Command for unknown debugger ID '{debuggerId}' received.")
349 sock = (
350 self.__connections[self.__mainClientId] if self.__mainClientId else None
351 )
352 if sock:
353 self.__server.sendJsonCommand(jsonStr, sock)

eric ide

mercurial