Skip to content

Commit 339d7a5

Browse files
committed
Added decorator to encapsulate the fork multiprocessing workaround.
1 parent cbc721b commit 339d7a5

File tree

1 file changed

+19
-7
lines changed

1 file changed

+19
-7
lines changed

importlib_metadata/__init__.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,24 @@ def find_distributions(self, context=Context()) -> Iterable[Distribution]:
787787
"""
788788

789789

790+
def _clear_lru_cache_after_fork(func):
791+
"""Wrap ``func`` with ``functools.lru_cache`` and clear it after ``fork``.
792+
793+
``FastPath`` caches zip-backed ``pathlib.Path`` objects that keep a
794+
reference to the parent's open ``ZipFile`` handle. Re-using a cached
795+
instance in a forked child can therefore resurrect invalid file pointers
796+
and trigger ``BadZipFile``/``OSError`` failures (python/importlib_metadata#520).
797+
Registering ``cache_clear`` with ``os.register_at_fork`` ensures every
798+
process gets a pristine cache and opens its own archive handles.
799+
"""
800+
801+
cached = functools.lru_cache()(func)
802+
register = getattr(os, 'register_at_fork', None)
803+
if register is not None:
804+
register(after_in_child=cached.cache_clear)
805+
return cached
806+
807+
790808
class FastPath:
791809
"""
792810
Micro-optimized class for searching a root for children.
@@ -803,8 +821,7 @@ class FastPath:
803821
True
804822
"""
805823

806-
# The following cache is cleared at fork, see os.register_at_fork below
807-
@functools.lru_cache() # type: ignore[misc]
824+
@_clear_lru_cache_after_fork # type: ignore[misc]
808825
def __new__(cls, root):
809826
return super().__new__(cls)
810827

@@ -844,11 +861,6 @@ def mtime(self):
844861
def lookup(self, mtime):
845862
return Lookup(self)
846863

847-
# Clear FastPath.__new__ cache when forked, avoids trying to re-useing open
848-
# file pointers from zipp.Path/zipfile.Path objects in forked process
849-
os.register_at_fork(after_in_child=FastPath.__new__.cache_clear)
850-
851-
852864
class Lookup:
853865
"""
854866
A micro-optimized class for searching a (fast) path for metadata.

0 commit comments

Comments
 (0)