summaryrefslogtreecommitdiffstats
path: root/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
diff options
context:
space:
mode:
authorJorge Gorbe Moya <jgorbe@google.com>2019-04-01 20:37:22 +0000
committerJorge Gorbe Moya <jgorbe@google.com>2019-04-01 20:37:22 +0000
commit4665aca8ca769f1389d83f59e8774c749b2f9d88 (patch)
tree97f31e3387e0a794b47b8bd5d2996beccd51a4dc /lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
parent66d7eb97045e0fda283ff336297e1a46869152f6 (diff)
downloadbcm5719-llvm-4665aca8ca769f1389d83f59e8774c749b2f9d88.tar.gz
bcm5719-llvm-4665aca8ca769f1389d83f59e8774c749b2f9d88.zip
[lldb-vscode] Add logic to handle EOF when reading from lldb-vscode stdout.
Summary: This change prevents the lldb-vscode test harness from hanging up waiting for new messages when the lldb-vscode subprocess crashes. Now, when an EOF from the subprocess pipe is detected we enqueue a `None` packet in the received packets list. Then, during the message processing loop, we can use this `None` packet to tell apart the case where lldb-vscode has terminated unexpectedly from the normal situation where no pending messages means blocking and waiting for more data. I believe this should be enough to fix the issues with these tests hanging on multiple platforms. Once this lands, I'll prepare and test a separate change removing the @skipIfLinux annotations. Reviewers: clayborg, zturner Subscribers: lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D59849 llvm-svn: 357426
Diffstat (limited to 'lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py')
-rw-r--r--lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py76
1 files changed, 45 insertions, 31 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
index 99986bc96a2..4e09e6a43a4 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
@@ -52,11 +52,11 @@ def dump_memory(base_addr, data, num_per_line, outfile):
def read_packet(f, verbose=False, trace_file=None):
'''Decode a JSON packet that starts with the content length and is
- followed by the JSON bytes from a file 'f'
+ followed by the JSON bytes from a file 'f'. Returns None on EOF.
'''
line = f.readline().decode("utf-8")
if len(line) == 0:
- return None
+ return None # EOF.
# Watch for line that starts with the prefix
prefix = 'Content-Length: '
@@ -91,10 +91,10 @@ def read_packet_thread(vs_comm):
done = False
while not done:
packet = read_packet(vs_comm.recv, trace_file=vs_comm.trace_file)
- if packet:
- done = not vs_comm.handle_recv_packet(packet)
- else:
- done = True
+ # `packet` will be `None` on EOF. We want to pass it down to
+ # handle_recv_packet anyway so the main thread can handle unexpected
+ # termination of lldb-vscode and stop waiting for new packets.
+ done = not vs_comm.handle_recv_packet(packet)
class DebugCommunication(object):
@@ -146,6 +146,12 @@ class DebugCommunication(object):
self.output_condition.release()
return output
+ def enqueue_recv_packet(self, packet):
+ self.recv_condition.acquire()
+ self.recv_packets.append(packet)
+ self.recv_condition.notify()
+ self.recv_condition.release()
+
def handle_recv_packet(self, packet):
'''Called by the read thread that is waiting for all incoming packets
to store the incoming packet in "self.recv_packets" in a thread safe
@@ -153,6 +159,11 @@ class DebugCommunication(object):
indicate a new packet is available. Returns True if the caller
should keep calling this function for more packets.
'''
+ # If EOF, notify the read thread by enqueing a None.
+ if not packet:
+ self.enqueue_recv_packet(None)
+ return False
+
# Check the packet to see if is an event packet
keepGoing = True
packet_type = packet['type']
@@ -191,10 +202,7 @@ class DebugCommunication(object):
elif packet_type == 'response':
if packet['command'] == 'disconnect':
keepGoing = False
- self.recv_condition.acquire()
- self.recv_packets.append(packet)
- self.recv_condition.notify()
- self.recv_condition.release()
+ self.enqueue_recv_packet(packet)
return keepGoing
def send_packet(self, command_dict, set_sequence=True):
@@ -222,27 +230,33 @@ class DebugCommunication(object):
function will wait for the packet to arrive and return it when
it does.'''
while True:
- self.recv_condition.acquire()
- packet = None
- while True:
- for (i, curr_packet) in enumerate(self.recv_packets):
- packet_type = curr_packet['type']
- if filter_type is None or packet_type in filter_type:
- if (filter_event is None or
- (packet_type == 'event' and
- curr_packet['event'] in filter_event)):
- packet = self.recv_packets.pop(i)
- break
- if packet:
- break
- # Sleep until packet is received
- len_before = len(self.recv_packets)
- self.recv_condition.wait(timeout)
- len_after = len(self.recv_packets)
- if len_before == len_after:
- return None # Timed out
- self.recv_condition.release()
- return packet
+ try:
+ self.recv_condition.acquire()
+ packet = None
+ while True:
+ for (i, curr_packet) in enumerate(self.recv_packets):
+ if not curr_packet:
+ raise EOFError
+ packet_type = curr_packet['type']
+ if filter_type is None or packet_type in filter_type:
+ if (filter_event is None or
+ (packet_type == 'event' and
+ curr_packet['event'] in filter_event)):
+ packet = self.recv_packets.pop(i)
+ break
+ if packet:
+ break
+ # Sleep until packet is received
+ len_before = len(self.recv_packets)
+ self.recv_condition.wait(timeout)
+ len_after = len(self.recv_packets)
+ if len_before == len_after:
+ return None # Timed out
+ return packet
+ except EOFError:
+ return None
+ finally:
+ self.recv_condition.release()
return None
OpenPOWER on IntegriCloud