Skip to content

Commit 2e85b37

Browse files
committed
Report ps forest on doctest timeout
1 parent 5c8d9e9 commit 2e85b37

File tree

2 files changed

+32
-11
lines changed

2 files changed

+32
-11
lines changed

src/sage/doctest/forker.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2039,7 +2039,8 @@ def sel_exit():
20392039
w.copied_exitcode,
20402040
w.result,
20412041
w.output,
2042-
pid=w.copied_pid)
2042+
pid=w.copied_pid,
2043+
process_tree_before_kill=w.process_tree_before_kill)
20432044

20442045
pending_tests -= 1
20452046

@@ -2272,7 +2273,8 @@ def __init__(self, source, options, funclist=[], baseline=None):
22722273
self.messages = ""
22732274

22742275
# Has this worker been killed (because of a time out)?
2275-
self.killed = False
2276+
self.killed: bool = False
2277+
self.process_tree_before_kill: str | None = None
22762278

22772279
def run(self):
22782280
"""
@@ -2502,6 +2504,17 @@ def kill(self):
25022504
sage: W.is_alive()
25032505
False
25042506
"""
2507+
try:
2508+
import subprocess
2509+
self.process_tree_before_kill = subprocess.run(["ps", "-ef", "--cols", "1000", "--forest"],
2510+
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL,
2511+
text=True, errors="ignore").stdout
2512+
except FileNotFoundError: # ps not available? Unlikely
2513+
pass
2514+
except subprocess.CalledProcessError:
2515+
self.process_tree_before_kill = subprocess.run(["ps", "-efwww"],
2516+
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL,
2517+
text=True, errors="ignore").stdout
25052518

25062519
if self.rmessages is not None:
25072520
os.close(self.rmessages)

src/sage/doctest/reporting.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ def report_head(self, source, fail_msg=None):
222222
cmd += f" [failed in baseline: {failed}]"
223223
return cmd
224224

225-
def _log_failure(self, source, fail_msg, event, output=None):
225+
def _log_failure(self, source, fail_msg, event, output=None, *, process_tree_before_kill=None):
226226
r"""
227227
Report on the result of a failed doctest run.
228228
@@ -236,6 +236,8 @@ def _log_failure(self, source, fail_msg, event, output=None):
236236
237237
- ``output`` -- (optional) string
238238
239+
- ``process_tree_before_kill`` -- (optional) string
240+
239241
EXAMPLES::
240242
241243
sage: from sage.doctest.reporting import DocTestReporter
@@ -265,13 +267,9 @@ def _log_failure(self, source, fail_msg, event, output=None):
265267
"""
266268
log = self.controller.log
267269
format = self.controller.options.format
270+
stars = "*" * 70
268271
if format == 'sage':
269-
stars = "*" * 70
270272
log(f" {fail_msg}\n{stars}\n")
271-
if output:
272-
log(f"Tests run before {event}:")
273-
log(output)
274-
log(stars)
275273
elif format == 'github':
276274
# https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#using-workflow-commands-to-access-toolkit-functions
277275
command = f'::error title={fail_msg}'
@@ -292,8 +290,18 @@ def _log_failure(self, source, fail_msg, event, output=None):
292290
log(command)
293291
else:
294292
raise ValueError(f'unknown format option: {format}')
295-
296-
def report(self, source, timeout, return_code, results, output, pid=None):
293+
# we log the tests ran even in github mode. The last test information is redundant since it's included
294+
# in the {lineno} above, but the printed outputs of previously ran tests are not
295+
if output:
296+
log(f"Tests run before {event}:")
297+
log(output)
298+
log(stars)
299+
if process_tree_before_kill:
300+
log("Process tree before kill:")
301+
log(process_tree_before_kill)
302+
log(stars)
303+
304+
def report(self, source, timeout, return_code, results, output, pid=None, *, process_tree_before_kill=None):
297305
"""
298306
Report on the result of running doctests on a given source.
299307
@@ -507,7 +515,7 @@ def report(self, source, timeout, return_code, results, output, pid=None):
507515
fail_msg += " (and interrupt failed)"
508516
else:
509517
fail_msg += " (with %s after interrupt)" % signal_name(sig)
510-
self._log_failure(source, fail_msg, f"{process_name} timed out", output)
518+
self._log_failure(source, fail_msg, f"{process_name} timed out", output, process_tree_before_kill=process_tree_before_kill)
511519
postscript['lines'].append(self.report_head(source, fail_msg))
512520
stats[basename] = {"failed": True, "walltime": 1e6, "ntests": ntests}
513521
if not baseline.get('failed', False):

0 commit comments

Comments
 (0)