Skip to content
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

[Bug] [Crash][Reproducible] EOFError: Ran out of input when import yapf with multiprocess #1204

Closed
whlook opened this issue Feb 27, 2024 · 4 comments · Fixed by #1243
Closed

Comments

@whlook
Copy link

whlook commented Feb 27, 2024

previous similar issue #1164

Problems

  • When i use yapf (just import it) in multiprocess program, it will crash with 'EOFError: Ran out of inpu',log info below:

image

Reproduction

  1. yapf==0.40.2
  2. rm -r ~/.cache/YAPF
  3. run this python code:
 import multiprocessing
 
 def proc():
     import yapf
 
 if __name__ == "__main__":
     pp=[]
     for i in range(100):
         p = multiprocessing.Process(target=proc)
         pp.append(p)
 
     for p in pp:
         p.start()
 
     for p in pp:
         p.join()
                                                   

Reason

the problem code is here:

When in multi process enviroment,some process will create grammar cache(when ~/.cache/YAPF not exists), before the process write to the cache file, other process will see the file exist and load it, but the cache file is empty right now , so EOFError will raise and the program crashed.

How to fix it?

@whlook whlook changed the title [Bug] [Crash] EOFError: Ran out of input when import yapf with multiprocess [Bug] [Crash][Reproducible] EOFError: Ran out of input when import yapf with multiprocess Feb 27, 2024
@hartwork
Copy link
Contributor

hartwork commented Oct 3, 2024

@whlook that's a great report, in particular the reproducer is very handy — thank you!

I have a pull request coming up for this — should be auto-linked below in a minute or two —, and I would like to share my extended version of your reproducer below:

import multiprocessing

def cleanup():
    import os
    import yapf
    from yapf_third_party._ylib2to3.pgen2.driver import _generate_pickle_name
    for i in ("Grammar.txt", "PatternGrammar.txt"):
        filename = _generate_pickle_name(i)
        print(f"  Removing {filename}...")
        os.remove(_generate_pickle_name(i))

def proc():
    import yapf

if __name__ == "__main__":
    max_parallelity = 30
    for parallelity in range(2, max_parallelity + 1):
        print("Cleaning up...")
        cleanup_p = multiprocessing.Process(target=cleanup)
        cleanup_p.start()
        cleanup_p.join()

        print(f"Testing for the race condition with {parallelity} processes...")
        pp = []
        for i in range(parallelity):
            p = multiprocessing.Process(target=proc)
            pp.append(p)

        for p in pp:
            p.start()

        for p in pp:
            p.join()

        if any(p.exitcode != 0 for p in pp):
            print(f"Done, race condition proven above, took {parallelity} processes.")
            break
    else:
        print("Done, no luck crashing this time.")

rapids-bot bot pushed a commit to nv-morpheus/Morpheus that referenced this issue Jan 7, 2025
* fixes yapf issues google/yapf#1164 and google/yapf#1204

On hold for a Conda package of yapf v0.43.0 conda-forge/yapf-feedstock#40

## By Submitting this PR I confirm:
- I am familiar with the [Contributing Guidelines](https://github.com/nv-morpheus/Morpheus/blob/main/docs/source/developer_guide/contributing.md).
- When the PR is ready for review, new or existing tests cover these changes.
- When the PR is ready for review, the documentation is up to date with these changes.

Authors:
  - David Gardner (https://github.com/dagardner-nv)

Approvers:
  - Michael Demoret (https://github.com/mdemoret-nv)

URL: #2055
@TheUbuntuGuy
Copy link

This issue is not completely resolved as #1243 does not resolve the issue for me. When running highly parallel (128 processes on a server), I still get the same exception on the latest release 0.43.0, which has this fix. It is reproducible about half the time. It appears that always 2 processes crash with the same exception, so there is some kind of race still occurring.

Traceback (most recent call last):
  File "/usr/local/bin/yapf", line 5, in <module>
    from yapf import run_main
  File "/usr/local/lib/python3.11/dist-packages/yapf/__init__.py", line 40, in <module>
    from yapf.yapflib import yapf_api
  File "/usr/local/lib/python3.11/dist-packages/yapf/yapflib/yapf_api.py", line 38, in <module>
    from yapf.pyparser import pyparser
  File "/usr/local/lib/python3.11/dist-packages/yapf/pyparser/pyparser.py", line 44, in <module>
    from yapf.yapflib import format_token
  File "/usr/local/lib/python3.11/dist-packages/yapf/yapflib/format_token.py", line 23, in <module>
    from yapf.pytree import pytree_utils
  File "/usr/local/lib/python3.11/dist-packages/yapf/pytree/pytree_utils.py", line 30, in <module>
    from yapf_third_party._ylib2to3 import pygram
  File "/usr/local/lib/python3.11/dist-packages/yapf_third_party/_ylib2to3/pygram.py", line 29, in <module>
    python_grammar = driver.load_grammar(_GRAMMAR_FILE)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/yapf_third_party/_ylib2to3/pgen2/driver.py", line 248, in load_grammar
    g.load(gp)
  File "/usr/local/lib/python3.11/dist-packages/yapf_third_party/_ylib2to3/pgen2/grammar.py", line 128, in load
    d = pickle.load(f)
        ^^^^^^^^^^^^^^
EOFError: Ran out of input

@TheUbuntuGuy
Copy link

What is even more interesting is that the workaround of running python -c 'import yapf' prior to starting the multiprocess format operation helps improve stability to a failure rate of about 1 in 20, but does not resolve the issue completely.

@anmyachev
Copy link

This issue is not completely resolved as #1243 does not resolve the issue for me. When running highly parallel (128 processes on a server), I still get the same exception on the latest release 0.43.0, which has this fix. It is reproducible about half the time. It appears that always 2 processes crash with the same exception, so there is some kind of race still occurring.

Traceback (most recent call last):
  File "/usr/local/bin/yapf", line 5, in <module>
    from yapf import run_main
  File "/usr/local/lib/python3.11/dist-packages/yapf/__init__.py", line 40, in <module>
    from yapf.yapflib import yapf_api
  File "/usr/local/lib/python3.11/dist-packages/yapf/yapflib/yapf_api.py", line 38, in <module>
    from yapf.pyparser import pyparser
  File "/usr/local/lib/python3.11/dist-packages/yapf/pyparser/pyparser.py", line 44, in <module>
    from yapf.yapflib import format_token
  File "/usr/local/lib/python3.11/dist-packages/yapf/yapflib/format_token.py", line 23, in <module>
    from yapf.pytree import pytree_utils
  File "/usr/local/lib/python3.11/dist-packages/yapf/pytree/pytree_utils.py", line 30, in <module>
    from yapf_third_party._ylib2to3 import pygram
  File "/usr/local/lib/python3.11/dist-packages/yapf_third_party/_ylib2to3/pygram.py", line 29, in <module>
    python_grammar = driver.load_grammar(_GRAMMAR_FILE)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/yapf_third_party/_ylib2to3/pgen2/driver.py", line 248, in load_grammar
    g.load(gp)
  File "/usr/local/lib/python3.11/dist-packages/yapf_third_party/_ylib2to3/pgen2/grammar.py", line 128, in load
    d = pickle.load(f)
        ^^^^^^^^^^^^^^
EOFError: Ran out of input

Hi @TheUbuntuGuy,

I have a patch for this problem: #1263. BTW do you have a chance to try it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants