Skip to content

Commit 4e0e813

Browse files
committed
Added decorator to encapsulate the fork multiprocessing workaround.
1 parent fd3c321 commit 4e0e813

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
@@ -786,6 +786,24 @@ def find_distributions(self, context=Context()) -> Iterable[Distribution]:
786786
"""
787787

788788

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

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

@@ -843,11 +860,6 @@ def mtime(self):
843860
def lookup(self, mtime):
844861
return Lookup(self)
845862

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

0 commit comments

Comments
 (0)