bpo-32030: Enhance Py_Main() (#4412)

Parse more env vars in Py_Main():

* Add more options to _PyCoreConfig:

  * faulthandler
  * tracemalloc
  * importtime

* Move code to parse environment variables from _Py_InitializeCore()
  to Py_Main(). This change fixes a regression from Python 3.6:
  PYTHONUNBUFFERED is now read before calling pymain_init_stdio().
* _PyFaulthandler_Init() and _PyTraceMalloc_Init() now take an
  argument to decide if the module has to be enabled at startup.
* tracemalloc_start() is now responsible to check the maximum number
  of frames.

Other changes:

* Cleanup Py_Main():

  * Rename some pymain_xxx() subfunctions
  * Add pymain_run_python() subfunction

* Cleanup Py_NewInterpreter()
* _PyInterpreterState_Enable() now reports failure
* init_hash_secret() now considers pyurandom() failure as an "user
  error": don't fail with abort().
* pymain_optlist_append() and pymain_strdup() now sets err on memory
  allocation failure.
This commit is contained in:
Victor Stinner 2017-11-15 18:11:45 -08:00 committed by GitHub
parent f7e5b56c37
commit a7368ac636
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 495 additions and 411 deletions

View file

@ -829,16 +829,23 @@ class TestCommandLine(unittest.TestCase):
stdout = stdout.rstrip()
self.assertEqual(stdout, b'10')
def check_env_var_invalid(self, nframe):
with support.SuppressCrashReport():
ok, stdout, stderr = assert_python_failure(
'-c', 'pass',
PYTHONTRACEMALLOC=str(nframe))
if b'ValueError: the number of frames must be in range' in stderr:
return
if b'PYTHONTRACEMALLOC: invalid number of frames' in stderr:
return
self.fail(f"unexpeced output: {stderr!a}")
def test_env_var_invalid(self):
for nframe in (-1, 0, 2**30):
with self.subTest(nframe=nframe):
with support.SuppressCrashReport():
ok, stdout, stderr = assert_python_failure(
'-c', 'pass',
PYTHONTRACEMALLOC=str(nframe))
self.assertIn(b'PYTHONTRACEMALLOC: invalid '
b'number of frames',
stderr)
self.check_env_var_invalid(nframe)
def test_sys_xoptions(self):
for xoptions, nframe in (
@ -852,15 +859,21 @@ class TestCommandLine(unittest.TestCase):
stdout = stdout.rstrip()
self.assertEqual(stdout, str(nframe).encode('ascii'))
def check_sys_xoptions_invalid(self, nframe):
args = ('-X', 'tracemalloc=%s' % nframe, '-c', 'pass')
with support.SuppressCrashReport():
ok, stdout, stderr = assert_python_failure(*args)
if b'ValueError: the number of frames must be in range' in stderr:
return
if b'-X tracemalloc=NFRAME: invalid number of frames' in stderr:
return
self.fail(f"unexpeced output: {stderr!a}")
def test_sys_xoptions_invalid(self):
for nframe in (-1, 0, 2**30):
with self.subTest(nframe=nframe):
with support.SuppressCrashReport():
args = ('-X', 'tracemalloc=%s' % nframe, '-c', 'pass')
ok, stdout, stderr = assert_python_failure(*args)
self.assertIn(b'-X tracemalloc=NFRAME: invalid '
b'number of frames',
stderr)
self.check_sys_xoptions_invalid(nframe)
@unittest.skipIf(_testcapi is None, 'need _testcapi')
def test_pymem_alloc0(self):