New issue 3060: Multiprocessing regression in PyPy 7.x
https://bitbucket.org/pypy/pypy/issues/3060/multiprocessing-regression-in-pypy-7x

Nathan Stocks:

I'm the maintainer of [Green](https://github.com/CleanCut/green) and I've run 
across what seems to be a very odd pypy3 bug in `multiprocessing/connection.py` 
specific to macOS.  This doesn't happen on any other version of Python nor on 
any platform that I test, also this didn’t happen on PyPy 6.0 and earlier, so I 
don’t suspect the python module itself, per se.

OS: macOS Mojave 10.14.6  
Pypy: `Python 3.6.1 (784b254d669919c872a505b807db8462b6140973, Jun 18 2019, 
05:54:52)` / `[PyPy 7.1.1-beta0 with GCC 4.2.1 Compatible Apple LLVM 10.0.1 
(clang-1001.0.46.4)] on darwin`

Steps to reproduce:

1. Install green

* `pip_pypy3 install green`

1. Run a portion of green's self-tests:

* `/usr/local/share/pypy3/green -vvv green.test.test_runner`

I observe 3\(!!!\) different crashes, each of which seem to implicate 
`multiprocessing/connection.py`.  As far as I can tell, which error you get is 
simply random chance, though the first type seems to occur most often for me.

Crash Type 1 seems to be the most common, an indefinite hang which requires 
pressing Ctrl-C to break out of:

```
$ /usr/local/share/pypy3/green -vvv green.test.test_runner
Green 2.16.1, Coverage 4.5.4, Python 3.6.1

green.test.test_runner
  TestInitializerOrFinalizer
.   Given a blank dotted function, calling the initializer/finalizer does 
nothing.
.   An importable, callable object...crashes.
.   Given an actual importable module and function, the function is run.
.   An importable, but not-callable-object also raises an 
InitializerOrFinalizerError.
.   Given an unimportable module, an InitializerOrFinalizerError is raised.
  TestProcesses
.   Bad syntax in a testfile is caught as a test error.
.   run() can catch SIGINT while running a process.
.   If tempfile.gettempdir() is used for dir, using same testfile name will not 
collide.
.   args.processes = 0 causes auto-detection of number of processes.
.   run() does not crash with empty suite and processes
.   Running coverage in process mode doesn't crash
.   Exceptions that escape the test framework get caught by poolRunner and 
reported as a failure.  For example, the testtools implementation of TestCase 
unwisely (but deliberately) lets SystemExit exceptions through.
  TestRun
.   run() can use a GreenStream for output.
.   A failing test case causes the whole run to report 'FAILED'
.   failfast causes the testing to stop after the first failure.
.   When we don't find any tests, we say so.
.   run() can use sys.stdout as the stream.
.   Raising a SystemExit gets caught and reported.
.   verbose=3 causes version output, and an empty test case passes.
E   setting warnings='always' doesn't crash
^CProcess DaemonlessPoolWorker-1:
Traceback (most recent call last):
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/process.py",
 line 252, in _bootstrap
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/util.py", 
line 288, in _exit_function
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/util.py", 
line 254, in _run_finalizers
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/util.py", 
line 186, in __call__
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/managers.py",
 line 615, in _finalize_manager
    process.join(timeout=1.0)
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/process.py",
 line 121, in join
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/popen_fork.py",
 line 48, in wait
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/connection.py",
 line 911, in wait
    ready = selector.select(timeout)
  File "/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/selectors.py", line 
376, in select
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/unittest/signals.py", line 
36, in __call__
KeyboardInterrupt

Error in green.test.test_runner.TestRun.test_warnings
  File "/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/unittest/case.py", 
line 59, in testPartExecutor
    yield
  File "/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/unittest/case.py", 
line 601, in run
    testMethod()
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/site-packages/green/test/test_runner.py",
 line 182, in test_warnings
    result = run(tests, self.stream, self.args)
  File "/usr/local/Cellar/pypy3/7.1.1/libexec/site-packages/green/runner.py", 
line 87, in run
    manager = multiprocessing.Manager()
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/context.py",
 line 56, in Manager
    m.start()
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/managers.py",
 line 503, in start
    reader, writer = connection.Pipe(duplex=False)
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/connection.py",
 line 512, in Pipe
    fd1, fd2 = os.pipe()
OSError: [Errno 24] Too many open files

Warning: Some tests may not have been run.

Ran 20 tests in 10.948s using 8 processes

FAILED (errors=1, passes=19)
```

Here is Crash Type 2 talking about "bad message length":

```
$ /usr/local/share/pypy3/green -vvv green.test.test_runner
Green 2.16.1, Coverage 4.5.4, Python 3.6.1

green.test.test_runner
  TestInitializerOrFinalizer
.   Given a blank dotted function, calling the initializer/finalizer does 
nothing.
.   An importable, callable object...crashes.
.   Given an actual importable module and function, the function is run.
.   An importable, but not-callable-object also raises an 
InitializerOrFinalizerError.
.   Given an unimportable module, an InitializerOrFinalizerError is raised.
  TestProcesses
.   Bad syntax in a testfile is caught as a test error.
.   run() can catch SIGINT while running a process.
.   If tempfile.gettempdir() is used for dir, using same testfile name will not 
collide.
.   args.processes = 0 causes auto-detection of number of processes.
.   run() does not crash with empty suite and processes
.   Running coverage in process mode doesn't crash
.   Exceptions that escape the test framework get caught by poolRunner and 
reported as a failure.  For example, the testtools implementation of TestCase 
unwisely (but deliberately) lets SystemExit exceptions through.
  TestRun
.   run() can use a GreenStream for output.
.   A failing test case causes the whole run to report 'FAILED'
.   failfast causes the testing to stop after the first failure.
.   When we don't find any tests, we say so.
.   run() can use sys.stdout as the stream.
.   Raising a SystemExit gets caught and reported.
.   verbose=3 causes version output, and an empty test case passes.
E   setting warnings='always' doesn't crash

Error in green.test.test_runner.TestRun.test_warnings
  File "/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/unittest/case.py", 
line 59, in testPartExecutor
    yield
  File "/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/unittest/case.py", 
line 601, in run
    testMethod()
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/site-packages/green/test/test_runner.py",
 line 182, in test_warnings
    result = run(tests, self.stream, self.args)
  File "/usr/local/Cellar/pypy3/7.1.1/libexec/site-packages/green/runner.py", 
line 89, in run
    for target in toParallelTargets(suite, args.targets)]
  File "/usr/local/Cellar/pypy3/7.1.1/libexec/site-packages/green/runner.py", 
line 89, in <listcomp>
    for target in toParallelTargets(suite, args.targets)]
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/managers.py",
 line 662, in temp
    token, exp = self._create(typeid, *args, **kwds)
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/managers.py",
 line 554, in _create
    conn = self._Client(self._address, authkey=self._authkey)
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/connection.py",
 line 493, in Client
    answer_challenge(c, authkey)
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/connection.py",
 line 732, in answer_challenge
    message = connection.recv_bytes(256)         # reject large message
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/connection.py",
 line 218, in recv_bytes
    self._bad_message_length()
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/connection.py",
 line 151, in _bad_message_length
    raise OSError("bad message length")
OSError: bad message length

Ran 20 tests in 5.613s using 8 processes

FAILED (errors=1, passes=19)
```

And finally Crash Type 3, talking about an "EOF Error":

```
$ /usr/local/share/pypy3/green -vvv green.test.test_runner
Green 2.16.1, Coverage 4.5.4, Python 3.6.1

green.test.test_runner
  TestInitializerOrFinalizer
.   Given a blank dotted function, calling the initializer/finalizer does 
nothing.
.   An importable, callable object...crashes.
.   Given an actual importable module and function, the function is run.
.   An importable, but not-callable-object also raises an 
InitializerOrFinalizerError.
.   Given an unimportable module, an InitializerOrFinalizerError is raised.
  TestProcesses
.   Bad syntax in a testfile is caught as a test error.
.   run() can catch SIGINT while running a process.
.   If tempfile.gettempdir() is used for dir, using same testfile name will not 
collide.
.   args.processes = 0 causes auto-detection of number of processes.
.   run() does not crash with empty suite and processes
.   Running coverage in process mode doesn't crash
.   Exceptions that escape the test framework get caught by poolRunner and 
reported as a failure.  For example, the testtools implementation of TestCase 
unwisely (but deliberately) lets SystemExit exceptions through.
  TestRun
.   run() can use a GreenStream for output.
.   A failing test case causes the whole run to report 'FAILED'
.   failfast causes the testing to stop after the first failure.
.   When we don't find any tests, we say so.
.   run() can use sys.stdout as the stream.
.   Raising a SystemExit gets caught and reported.
.   verbose=3 causes version output, and an empty test case passes.
E   setting warnings='always' doesn't crash

Error in green.test.test_runner.TestRun.test_warnings
  File "/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/unittest/case.py", 
line 59, in testPartExecutor
    yield
  File "/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/unittest/case.py", 
line 601, in run
    testMethod()
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/site-packages/green/test/test_runner.py",
 line 182, in test_warnings
    result = run(tests, self.stream, self.args)
  File "/usr/local/Cellar/pypy3/7.1.1/libexec/site-packages/green/runner.py", 
line 87, in run
    manager = multiprocessing.Manager()
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/context.py",
 line 56, in Manager
    m.start()
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/managers.py",
 line 517, in start
    self._address = reader.recv()
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/connection.py",
 line 250, in recv
    buf = self._recv_bytes()
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/connection.py",
 line 407, in _recv_bytes
    buf = self._recv(4)
  File 
"/usr/local/Cellar/pypy3/7.1.1/libexec/lib-python/3/multiprocessing/connection.py",
 line 383, in _recv
    raise EOFError
EOFError

Ran 20 tests in 4.402s using 8 processes

FAILED (errors=1, passes=19)
```


_______________________________________________
pypy-issue mailing list
pypy-issue@python.org
https://mail.python.org/mailman/listinfo/pypy-issue

Reply via email to