bpo-30258: regrtest handles child process crash (#1431) · python/cpython@c991eb2 (original) (raw)
`@@ -220,6 +220,7 @@
`
220
220
`SKIPPED = -2
`
221
221
`RESOURCE_DENIED = -3
`
222
222
`INTERRUPTED = -4
`
``
223
`+
CHILD_ERROR = -5 # error in a child process
`
223
224
``
224
225
`from test import test_support
`
225
226
``
`@@ -466,7 +467,8 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
`
466
467
``
467
468
`def accumulate_result(test, result):
`
468
469
`ok, test_time = result
`
469
``
`-
test_times.append((test_time, test))
`
``
470
`+
if ok not in (CHILD_ERROR, INTERRUPTED):
`
``
471
`+
test_times.append((test_time, test))
`
470
472
`if ok == PASSED:
`
471
473
`good.append(test)
`
472
474
`elif ok == FAILED:
`
`@@ -478,6 +480,9 @@ def accumulate_result(test, result):
`
478
480
`elif ok == RESOURCE_DENIED:
`
479
481
`skipped.append(test)
`
480
482
`resource_denieds.append(test)
`
``
483
`+
else:
`
``
484
`+
CHILD_ERROR
`
``
485
`+
bad.append(test)
`
481
486
``
482
487
`if forever:
`
483
488
`def test_forever(tests=list(selected)):
`
`@@ -533,9 +538,17 @@ def work():
`
533
538
`universal_newlines=True,
`
534
539
`close_fds=(os.name != 'nt'))
`
535
540
`stdout, stderr = popen.communicate()
`
``
541
`+
retcode = popen.wait()
`
``
542
+
536
543
`# Strip last refcount output line if it exists, since it
`
537
544
`# comes from the shutdown of the interpreter in the subcommand.
`
538
545
`stderr = debug_output_pat.sub("", stderr)
`
``
546
+
``
547
`+
if retcode != 0:
`
``
548
`+
result = (CHILD_ERROR, "Exit code %s" % retcode)
`
``
549
`+
output.put((test, stdout.rstrip(), stderr.rstrip(),
`
``
550
`+
result))
`
``
551
+
539
552
`stdout, _, result = stdout.strip().rpartition("\n")
`
540
553
`if not result:
`
541
554
`output.put((None, None, None, None))
`
`@@ -545,9 +558,11 @@ def work():
`
545
558
`except BaseException:
`
546
559
`output.put((None, None, None, None))
`
547
560
`raise
`
``
561
+
548
562
`workers = [Thread(target=work) for i in range(use_mp)]
`
549
563
`for worker in workers:
`
550
564
`worker.start()
`
``
565
+
551
566
`finished = 0
`
552
567
`test_index = 1
`
553
568
`try:
`
`@@ -556,21 +571,24 @@ def work():
`
556
571
`if test is None:
`
557
572
`finished += 1
`
558
573
`continue
`
``
574
`+
accumulate_result(test, result)
`
``
575
`+
if not quiet:
`
``
576
`+
fmt = "[{1:{0}}{2}/{3}] {4}" if bad else "[{1:{0}}{2}] {4}"
`
``
577
`+
print(fmt.format(
`
``
578
`+
test_count_width, test_index, test_count,
`
``
579
`+
len(bad), test))
`
``
580
+
559
581
`if stdout:
`
560
582
`print stdout
`
``
583
`+
sys.stdout.flush()
`
561
584
`if stderr and not pgo:
`
562
585
`print >>sys.stderr, stderr
`
563
``
`-
sys.stdout.flush()
`
564
586
`sys.stderr.flush()
`
``
587
+
565
588
`if result[0] == INTERRUPTED:
`
566
589
`assert result[1] == 'KeyboardInterrupt'
`
567
590
`raise KeyboardInterrupt # What else?
`
568
``
`-
accumulate_result(test, result)
`
569
``
`-
if not quiet:
`
570
``
`-
fmt = "[{1:{0}}{2}/{3}] {4}" if bad else "[{1:{0}}{2}] {4}"
`
571
``
`-
print(fmt.format(
`
572
``
`-
test_count_width, test_index, test_count,
`
573
``
`-
len(bad), test))
`
``
591
+
574
592
`test_index += 1
`
575
593
`except KeyboardInterrupt:
`
576
594
`interrupted = True
`
`@@ -738,6 +756,7 @@ def runtest(test, verbose, quiet,
`
738
756
` for Profile Guided Optimization build
`
739
757
``
740
758
` Returns one of the test result constants:
`
``
759
`+
CHILD_ERROR Child process crashed
`
741
760
` INTERRUPTED KeyboardInterrupt when run under -j
`
742
761
` RESOURCE_DENIED test skipped because resource denied
`
743
762
` SKIPPED test skipped for some other reason
`