mirror of
https://github.com/python/cpython.git
synced 2025-08-12 21:11:35 +00:00

Under some conditions the earlier fix for bpo-18075, "Infinite recursion
tests triggering a segfault on Mac OS X", now causes failures on macOS
when attempting to change stack limit with resource.setrlimit
resource.RLIMIT_STACK, like regrtest does when running the test suite.
The reverted change had specified a non-default stack size when linking
the python executable on macOS. As of macOS 10.14.4, the previous
code causes a hard failure when running tests, although similar
failures had been seen under some conditions under some earlier
systems. Reverting the change to the interpreter stack size at link
time helped for release builds but caused some tests to fail when
built --with-pydebug. Try the opposite approach: continue to build
the interpreter with an increased stack size on macOS and remove
the failing setrlimit call in regrtest initialization. This will
definitely avoid the resource.RLIMIT_STACK error and should have
no, or fewer, side effects.
(cherry picked from commit 5bbbc733e6
)
Co-authored-by: Ned Deily <nad@python.org>
129 lines
4.3 KiB
Python
129 lines
4.3 KiB
Python
import atexit
|
|
import faulthandler
|
|
import os
|
|
import signal
|
|
import sys
|
|
import unittest
|
|
from test import support
|
|
try:
|
|
import gc
|
|
except ImportError:
|
|
gc = None
|
|
|
|
|
|
def setup_tests(ns):
|
|
try:
|
|
stderr_fd = sys.__stderr__.fileno()
|
|
except (ValueError, AttributeError):
|
|
# Catch ValueError to catch io.UnsupportedOperation on TextIOBase
|
|
# and ValueError on a closed stream.
|
|
#
|
|
# Catch AttributeError for stderr being None.
|
|
stderr_fd = None
|
|
else:
|
|
# Display the Python traceback on fatal errors (e.g. segfault)
|
|
faulthandler.enable(all_threads=True, file=stderr_fd)
|
|
|
|
# Display the Python traceback on SIGALRM or SIGUSR1 signal
|
|
signals = []
|
|
if hasattr(signal, 'SIGALRM'):
|
|
signals.append(signal.SIGALRM)
|
|
if hasattr(signal, 'SIGUSR1'):
|
|
signals.append(signal.SIGUSR1)
|
|
for signum in signals:
|
|
faulthandler.register(signum, chain=True, file=stderr_fd)
|
|
|
|
replace_stdout()
|
|
support.record_original_stdout(sys.stdout)
|
|
|
|
if ns.testdir:
|
|
# Prepend test directory to sys.path, so runtest() will be able
|
|
# to locate tests
|
|
sys.path.insert(0, os.path.abspath(ns.testdir))
|
|
|
|
# Some times __path__ and __file__ are not absolute (e.g. while running from
|
|
# Lib/) and, if we change the CWD to run the tests in a temporary dir, some
|
|
# imports might fail. This affects only the modules imported before os.chdir().
|
|
# These modules are searched first in sys.path[0] (so '' -- the CWD) and if
|
|
# they are found in the CWD their __file__ and __path__ will be relative (this
|
|
# happens before the chdir). All the modules imported after the chdir, are
|
|
# not found in the CWD, and since the other paths in sys.path[1:] are absolute
|
|
# (site.py absolutize them), the __file__ and __path__ will be absolute too.
|
|
# Therefore it is necessary to absolutize manually the __file__ and __path__ of
|
|
# the packages to prevent later imports to fail when the CWD is different.
|
|
for module in sys.modules.values():
|
|
if hasattr(module, '__path__'):
|
|
for index, path in enumerate(module.__path__):
|
|
module.__path__[index] = os.path.abspath(path)
|
|
if getattr(module, '__file__', None):
|
|
module.__file__ = os.path.abspath(module.__file__)
|
|
|
|
if ns.huntrleaks:
|
|
unittest.BaseTestSuite._cleanup = False
|
|
|
|
if ns.memlimit is not None:
|
|
support.set_memlimit(ns.memlimit)
|
|
|
|
if ns.threshold is not None:
|
|
gc.set_threshold(ns.threshold)
|
|
|
|
suppress_msvcrt_asserts(ns.verbose and ns.verbose >= 2)
|
|
|
|
support.use_resources = ns.use_resources
|
|
|
|
if hasattr(sys, 'addaudithook'):
|
|
# Add an auditing hook for all tests to ensure PySys_Audit is tested
|
|
def _test_audit_hook(name, args):
|
|
pass
|
|
sys.addaudithook(_test_audit_hook)
|
|
|
|
|
|
def suppress_msvcrt_asserts(verbose):
|
|
try:
|
|
import msvcrt
|
|
except ImportError:
|
|
return
|
|
|
|
msvcrt.SetErrorMode(msvcrt.SEM_FAILCRITICALERRORS|
|
|
msvcrt.SEM_NOALIGNMENTFAULTEXCEPT|
|
|
msvcrt.SEM_NOGPFAULTERRORBOX|
|
|
msvcrt.SEM_NOOPENFILEERRORBOX)
|
|
try:
|
|
msvcrt.CrtSetReportMode
|
|
except AttributeError:
|
|
# release build
|
|
return
|
|
|
|
for m in [msvcrt.CRT_WARN, msvcrt.CRT_ERROR, msvcrt.CRT_ASSERT]:
|
|
if verbose:
|
|
msvcrt.CrtSetReportMode(m, msvcrt.CRTDBG_MODE_FILE)
|
|
msvcrt.CrtSetReportFile(m, msvcrt.CRTDBG_FILE_STDERR)
|
|
else:
|
|
msvcrt.CrtSetReportMode(m, 0)
|
|
|
|
|
|
|
|
def replace_stdout():
|
|
"""Set stdout encoder error handler to backslashreplace (as stderr error
|
|
handler) to avoid UnicodeEncodeError when printing a traceback"""
|
|
stdout = sys.stdout
|
|
try:
|
|
fd = stdout.fileno()
|
|
except ValueError:
|
|
# On IDLE, sys.stdout has no file descriptor and is not a TextIOWrapper
|
|
# object. Leaving sys.stdout unchanged.
|
|
#
|
|
# Catch ValueError to catch io.UnsupportedOperation on TextIOBase
|
|
# and ValueError on a closed stream.
|
|
return
|
|
|
|
sys.stdout = open(fd, 'w',
|
|
encoding=stdout.encoding,
|
|
errors="backslashreplace",
|
|
closefd=False,
|
|
newline='\n')
|
|
|
|
def restore_stdout():
|
|
sys.stdout.close()
|
|
sys.stdout = stdout
|
|
atexit.register(restore_stdout)
|