Skip to content
This repository was archived by the owner on Jan 23, 2024. It is now read-only.

Commit c2da9cb

Browse files
emrekultursayEmre Kultursay
authored andcommitted
Catch per-variable exceptions at a finer granularity so that unexpected runtime
errors at certain variables do not corrupt the entire breakpoint. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=184028582
1 parent 37ff148 commit c2da9cb

1 file changed

Lines changed: 49 additions & 25 deletions

File tree

src/googleclouddebugger/capture_collector.py

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -293,9 +293,6 @@ def Collect(self, top_frame):
293293
frame = top_frame
294294
top_line = self.breakpoint['location']['line']
295295
breakpoint_frames = self.breakpoint['stackFrames']
296-
# Number of entries in _var_table. Starts at 1 (index 0 is the 'buffer full'
297-
# status value).
298-
num_vars = 1
299296
try:
300297
# Evaluate watched expressions.
301298
if 'expressions' in self.breakpoint:
@@ -323,33 +320,31 @@ def Collect(self, top_frame):
323320
})
324321
frame = frame.f_back
325322

326-
# Explore variables table in BFS fashion. The variables table will grow
327-
# inside CaptureVariable as we encounter new references.
328-
while (num_vars < len(self._var_table)) and (
329-
self._total_size < self.max_size):
330-
try:
331-
self._var_table[num_vars] = self.CaptureVariable(
332-
self._var_table[num_vars], 0, self.default_capture_limits,
333-
can_enqueue=False)
334-
num_vars += 1
335-
except RuntimeError as e:
336-
# Capture details on the failure and let the outer handler convert it
337-
# to a status.
338-
raise RuntimeError(
339-
'Failed while capturing an object of type {0}: {1}'.format(
340-
type(self._var_table[num_vars]), e))
341-
342323
except BaseException as e: # pylint: disable=broad-except
343-
# The variable table will get serialized even though there was a
344-
# failure. The results can be useful for diagnosing the internal
345-
# error so just trim the excess values.
324+
# The variable table will get serialized even though there was a failure.
325+
# The results can be useful for diagnosing the internal error.
346326
self.breakpoint['status'] = {
347327
'isError': True,
348328
'description': {
349-
'format': (
350-
'INTERNAL ERROR: Debugger failed to capture frame $0: $1'),
329+
'format': ('INTERNAL ERROR: Failed while capturing locals '
330+
'of frame $0: $1'),
351331
'parameters': [str(len(breakpoint_frames)), str(e)]}}
352332

333+
# Number of entries in _var_table. Starts at 1 (index 0 is the 'buffer full'
334+
# status value).
335+
num_vars = 1
336+
337+
# Explore variables table in BFS fashion. The variables table will grow
338+
# inside CaptureVariable as we encounter new references.
339+
while (num_vars < len(self._var_table)) and (
340+
self._total_size < self.max_size):
341+
self._var_table[num_vars] = self.CaptureVariable(
342+
self._var_table[num_vars], 0, self.default_capture_limits,
343+
can_enqueue=False)
344+
345+
# Move on to the next entry in the variable table.
346+
num_vars += 1
347+
353348
# Trim variables table and change make all references to variables that
354349
# didn't make it point to var_index of 0 ("buffer full")
355350
self.TrimVariableTable(num_vars)
@@ -481,6 +476,35 @@ def CaptureVariablesList(self, items, depth, empty_message, limits):
481476
return v
482477

483478
def CaptureVariable(self, value, depth, limits, can_enqueue=True):
479+
"""Try-Except wrapped version of CaptureVariableInternal."""
480+
try:
481+
return self.CaptureVariableInternal(value, depth, limits, can_enqueue)
482+
except RuntimeError as e:
483+
# Record as an error in the variable, and continue iterating.
484+
return {
485+
'status': {
486+
'is_error': True,
487+
'refers_to': 'VARIABLE_VALUE',
488+
'description': {
489+
'format': 'Failed while capturing variable: $0',
490+
'parameters': [str(e)]
491+
}
492+
}
493+
}
494+
except BaseException as e: # pylint: disable=broad-except
495+
# Record as an internal error in the variable, and continue iterating.
496+
return {
497+
'status': {
498+
'isError': True,
499+
'description': {
500+
'format': ('INTERNAL ERROR: Failed while capturing '
501+
'variable: $0: $1'),
502+
'parameters': [str(e)]
503+
}
504+
}
505+
}
506+
507+
def CaptureVariableInternal(self, value, depth, limits, can_enqueue=True):
484508
"""Captures a single nameless object into Variable message.
485509
486510
TODO(vlif): safely evaluate iterable types.
@@ -541,7 +565,7 @@ def CaptureVariable(self, value, depth, limits, can_enqueue=True):
541565
index = len(self._var_table)
542566
self._var_table_index[id(value)] = index
543567
self._var_table.append(value)
544-
self._total_size += 4 # number of characters to accomodate a number.
568+
self._total_size += 4 # number of characters to accommodate a number.
545569
return {'varTableIndex': index}
546570

547571
for pretty_printer in CaptureCollector.pretty_printers:

0 commit comments

Comments
 (0)