jaraco / pip-run

pip-run - dynamic dependency loader for Python

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Error tearing down an environment with a shared library (Windows)

jaraco opened this issue · comments

While reporting pganssle/zoneinfo#144, I encountered another error. On Windows, when trying to query for timezone info, I encounter a failure on exit when pip-run attempts to tear down the temporary environment:

 ~ [1] # py -3.8 -m pip-run backports.zoneinfo tzdata -- -c "import backports.zoneinfo; print(backports.zoneinfo.ZoneInfo('UTC') 
)"
UTC
Traceback (most recent call last):
  File "C:\Users\jaraco\.local\pip-run\pip_run\retention\destroy.py", line 9, in context
    yield pathlib.Path(td)
  File "C:\Users\jaraco\.local\pip-run\pip_run\deps.py", line 101, in load
    yield target
  File "C:\Users\jaraco\.local\pip-run\pip_run\__init__.py", line 14, in run
    raise SystemExit(launch.with_path(home, launch.infer_cmd(run_args)))
SystemExit: 0

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Python38\lib\shutil.py", line 616, in _rmtree_unsafe
    os.unlink(fullname)
PermissionError: [WinError 5] Access is denied: 'C:\\Users\\jaraco\\AppData\\Local\\Temp\\pip-run-fmtsvna1\\backports\\zoneinfo\\_czoneinfo.cp38-win_amd64.pyd'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Python38\lib\tempfile.py", line 802, in onerror
    _os.unlink(path)
PermissionError: [WinError 5] Access is denied: 'C:\\Users\\jaraco\\AppData\\Local\\Temp\\pip-run-fmtsvna1\\backports\\zoneinfo\\_czoneinfo.cp38-win_amd64.pyd'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Python38\lib\runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Python38\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\jaraco\.local\pip-run\pip-run.py", line 3, in <module>
    __name__ == '__main__' and run()
  File "C:\Users\jaraco\.local\pip-run\pip_run\__init__.py", line 14, in run
    raise SystemExit(launch.with_path(home, launch.infer_cmd(run_args)))
  File "C:\Python38\lib\contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "C:\Users\jaraco\.local\pip-run\pip_run\deps.py", line 101, in load
    yield target
  File "C:\Python38\lib\contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "C:\Users\jaraco\.local\pip-run\pip_run\retention\destroy.py", line 9, in context
    yield pathlib.Path(td)
  File "C:\Python38\lib\tempfile.py", line 827, in __exit__
    self.cleanup()
  File "C:\Python38\lib\tempfile.py", line 831, in cleanup
    self._rmtree(self.name)
  File "C:\Python38\lib\tempfile.py", line 813, in _rmtree
    _shutil.rmtree(name, onerror=onerror)
  File "C:\Python38\lib\shutil.py", line 740, in rmtree
    return _rmtree_unsafe(path, onerror)
  File "C:\Python38\lib\shutil.py", line 613, in _rmtree_unsafe
    _rmtree_unsafe(fullname, onerror)
  File "C:\Python38\lib\shutil.py", line 613, in _rmtree_unsafe
    _rmtree_unsafe(fullname, onerror)
  File "C:\Python38\lib\shutil.py", line 618, in _rmtree_unsafe
    onerror(os.unlink, fullname, sys.exc_info())
  File "C:\Python38\lib\tempfile.py", line 805, in onerror
    cls._rmtree(path)
  File "C:\Python38\lib\tempfile.py", line 813, in _rmtree
    _shutil.rmtree(name, onerror=onerror)
  File "C:\Python38\lib\shutil.py", line 740, in rmtree
    return _rmtree_unsafe(path, onerror)
  File "C:\Python38\lib\shutil.py", line 599, in _rmtree_unsafe
    onerror(os.scandir, path, sys.exc_info())
  File "C:\Python38\lib\shutil.py", line 596, in _rmtree_unsafe
    with os.scandir(path) as scandir_it:
NotADirectoryError: [WinError 267] The directory name is invalid: 'C:\\Users\\jaraco\\AppData\\Local\\Temp\\pip-run-fmtsvna1\\backports\\zoneinfo\\_czoneinfo.cp38-win_amd64.pyd'

The command executes, emits the successful output, and then attempts to tear down the environment, but the shared library (.pyd) is still in use. Perhaps this issue is not unique to backports.zoneinfo, but it's the first time I've encountered it.

It should be the case that the Python subprocess that held a handle to the shared library should be terminated before the temporary directory is cleaned up, but it seems it's not the case.

Perhaps pip-run should wait a moment to see if the handle is freed or perhaps just suppress the error and leave the temporary install.

It's a shame that Windows makes this so difficult.