Skip to content

Fork server doesn't flush stdout/stderr after preloading modules, potentially leaving buffered data to be inherited by child processes #135335

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
duaneg opened this issue Jun 10, 2025 · 0 comments
Labels
stdlib Python modules in the Lib dir topic-multiprocessing type-bug An unexpected behavior, bug, or error

Comments

@duaneg
Copy link
Contributor

duaneg commented Jun 10, 2025

Bug report

Bug description:

Files

a/__init__.py
import os
import time
print(f"init {os.getpid()} at {time.clock_gettime_ns(time.CLOCK_MONOTONIC)}")
repro.py
import multiprocessing
import os
import time

if __name__ == '__main__':
    print(f"run main {os.getpid()}")
    multiprocessing.set_forkserver_preload(['a'])
    for _ in range(2):
        p = multiprocessing.Process()
        p.start()
        p.join()
else:
    print(f"re-import main {os.getpid()} at {time.clock_gettime_ns(time.CLOCK_MONOTONIC)}")

Reproduction

  1. Create a new module a containing the __init__.py file above
  2. Run the repro.py script above, ensuring the module created is on PYTHONPATH

Result

> ./python repro.py
run main 1056488
init 1056490 at 151009034069836
re-import main 1056491 at 151009045273212
re-import main 1056492 at 151009051787587
> ./python repro.py | tee /dev/null
run main 1056607
init 1056610 at 151113770440639
re-import main 1056611 at 151113781130002
init 1056610 at 151113770440639
re-import main 1056612 at 151113787814593
init 1056610 at 151113770440639

Expected

The output to be the same when stdout is redirected as when it is not.

Analysis

This is due to fork server preloading a module that writes to stdout, but not flushing it. When a child process is spawned it inherits the buffered data and spuriously outputs it when it flushes its stdout. Note that #126631 prevents __main__ from being preloaded, so at present this will not be triggered by printing from __main__.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

@duaneg duaneg added the type-bug An unexpected behavior, bug, or error label Jun 10, 2025
@picnixz picnixz added stdlib Python modules in the Lib dir topic-multiprocessing labels Jun 10, 2025
duaneg added a commit to duaneg/cpython that referenced this issue Jun 10, 2025
…odules

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stdlib Python modules in the Lib dir topic-multiprocessing type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

2 participants