mirror of
https://github.com/python/cpython.git
synced 2025-11-01 22:21:35 +00:00
[3.14] gh-135335: flush stdout/stderr in forkserver after preloading modules (GH-135338) (#135670)
gh-135335: flush stdout/stderr in forkserver after preloading modules (GH-135338)
If a preloaded module writes to stdout or stderr, and the stream is buffered,
child processes will inherit the buffered data after forking. Attempt to
prevent this by flushing the streams after preload.
(cherry picked from commit 9877d191f4)
Co-authored-by: Duane Griffin <duaneg@dghda.com>
Co-authored-by: Mikhail Efimov <efimov.mikhail@gmail.com>
Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
parent
91914fd448
commit
9ac369cb73
4 changed files with 50 additions and 0 deletions
|
|
@ -6789,6 +6789,35 @@ def test_child_sys_path(self):
|
|||
self.assertEqual(child_sys_path[1:], sys.path[1:])
|
||||
self.assertIsNone(import_error, msg=f"child could not import {self._mod_name}")
|
||||
|
||||
def test_std_streams_flushed_after_preload(self):
|
||||
# gh-135335: Check fork server flushes standard streams after
|
||||
# preloading modules
|
||||
if multiprocessing.get_start_method() != "forkserver":
|
||||
self.skipTest("forkserver specific test")
|
||||
|
||||
# Create a test module in the temporary directory on the child's path
|
||||
# TODO: This can all be simplified once gh-126631 is fixed and we can
|
||||
# use __main__ instead of a module.
|
||||
dirname = os.path.join(self._temp_dir, 'preloaded_module')
|
||||
init_name = os.path.join(dirname, '__init__.py')
|
||||
os.mkdir(dirname)
|
||||
with open(init_name, "w") as f:
|
||||
cmd = '''if 1:
|
||||
import sys
|
||||
print('stderr', end='', file=sys.stderr)
|
||||
print('stdout', end='', file=sys.stdout)
|
||||
'''
|
||||
f.write(cmd)
|
||||
|
||||
name = os.path.join(os.path.dirname(__file__), 'mp_preload_flush.py')
|
||||
env = {'PYTHONPATH': self._temp_dir}
|
||||
_, out, err = test.support.script_helper.assert_python_ok(name, **env)
|
||||
|
||||
# Check stderr first, as it is more likely to be useful to see in the
|
||||
# event of a failure.
|
||||
self.assertEqual(err.decode().rstrip(), 'stderr')
|
||||
self.assertEqual(out.decode().rstrip(), 'stdout')
|
||||
|
||||
|
||||
class MiscTestCase(unittest.TestCase):
|
||||
def test__all__(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue