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

pip install can cache invalid wheels when the cache directory fills up #9964

Open
1 task done
godlygeek opened this issue May 7, 2021 · 0 comments
Open
1 task done
Labels
C: cache Dealing with cache and files in it type: bug A confirmed bug or unintended behavior

Comments

@godlygeek
Copy link
Contributor

Description

If there's not enough space left available in the user's cache directory for a wheel that has just been successfully built in a temp directory on a different disk, then this attempt to copy the built wheel into the cache directory fails:

shutil.move(wheel_path, dest_path)

Because moving files across disks is done by first copying the file then removing the original, this can result in an incomplete copy and an ENOSPC OSError being raised. The OSError is caught by pip, but the exception handler doesn't attempt to handle this case and clean up after it. Future runs of pip can then find this invalid, incomplete .whl file in the wheel cache, and go on to fail with zipfile.BadZipFile: File is not a zip file

Expected behavior

If writing the wheel file into the cache fails, pip should clean up after itself so the truncated file can't be found by future pip install calls.

pip version

master

Python version

3.9

OS

Linux

How to Reproduce

This was surprisingly difficult to reproduce, but I managed to get it by doing:

mkdir /tmp/too_small
sudo mount -t tmpfs -o size=400K tmpfs /tmp/too_small
python3.9 -m venv /tmp/venv
. /tmp/venv/bin/activate
pip --cache-dir=/tmp/too_small install --no-binary python-dateutil python-dateutil==2.8.1
python -m zipfile -l /tmp/too_small/wheels/*/*/*/*/python_dateutil*.whl

Output

$ mkdir /tmp/too_small
$ sudo mount -t tmpfs -o size=400K tmpfs /tmp/too_small
$ python3.9 -m venv /tmp/venv
$ . /tmp/venv/bin/activate
(venv) $ pip --cache-dir=/tmp/too_small install --no-binary python-dateutil python-dateutil==2.8.1
Looking in indexes: https://artprod.dev.bloomberg.com/artifactory/api/pypi/bloomberg-pypi/simple
Collecting python-dateutil==2.8.1
  Downloading https://artprod.dev.bloomberg.com/artifactory/api/pypi/bloomberg-pypi/packages/packages/be/ed/5bbc91f03fa4c839c4c7360375da77f9659af5f7086b7a7bdda65771c8e0/python-dateutil-2.8.1.tar.gz (331 kB)
     |████████████████████████████████| 331 kB 2.6 MB/s
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
    Preparing wheel metadata ... done
Collecting six>=1.5
  Downloading https://artprod.dev.bloomberg.com/artifactory/api/pypi/bloomberg-pypi/packages/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl (11 kB)
Building wheels for collected packages: python-dateutil
  Building wheel for python-dateutil (PEP 517) ... done
  WARNING: Building wheel for python-dateutil failed: [Errno 28] No space left on device: '/tmp/pip-wheel-kygit9c7/python_dateutil-2.8.1-py2.py3-none-any.whl' -> '/tmp/too_small/wheels/ed/3a/11/f3c3a429e4e3d97c7003108cca4a71a45a3f2ac87be8e3b11a/python_dateutil-2.8.1-py2.py3-none-any.whl'
Failed to build python-dateutil
ERROR: Could not build wheels for python-dateutil which use PEP 517 and cannot be installed directly
(venv) $ python -m zipfile -l /tmp/too_small/wheels/*/*/*/*/python_dateutil*.whl
Traceback (most recent call last):
  File "/opt/bb/lib/python3.9/runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/opt/bb/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/opt/bb/lib/python3.9/zipfile.py", line 2428, in <module>
    main()
  File "/opt/bb/lib/python3.9/zipfile.py", line 2394, in main
    with ZipFile(src, 'r') as zf:
  File "/opt/bb/lib/python3.9/zipfile.py", line 1257, in __init__
    self._RealGetContents()
  File "/opt/bb/lib/python3.9/zipfile.py", line 1324, in _RealGetContents
    raise BadZipFile("File is not a zip file")
__main__.BadZipFile: File is not a zip file
(venv) $

Code of Conduct

@godlygeek godlygeek added S: needs triage Issues/PRs that need to be triaged type: bug A confirmed bug or unintended behavior labels May 7, 2021
@ichard26 ichard26 added C: cache Dealing with cache and files in it and removed S: needs triage Issues/PRs that need to be triaged labels May 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: cache Dealing with cache and files in it type: bug A confirmed bug or unintended behavior
Projects
None yet
Development

No branches or pull requests

2 participants