6666}
6767
6868
69+ def _is_lock_infra_error (exc : BaseException ) -> bool :
70+ """Whether exc indicates broken lock infrastructure (not mere contention)."""
71+ if isinstance (exc , PermissionError ):
72+ return True
73+ if isinstance (exc , OSError ):
74+ return exc .errno in (errno .EACCES , errno .EPERM , errno .ENOLCK ,
75+ errno .ESTALE )
76+ return False
77+
78+
6979@contextlib .contextmanager
7080def config_file_lock (timeout : int = 10 ):
7181 """
@@ -77,47 +87,44 @@ def config_file_lock(timeout: int = 10):
7787 Args:
7888 timeout: Maximum time to wait for lock acquisition in seconds
7989 """
80- # Use a single global lock file in HF cache directory
81- # This serializes all model loading operations to prevent race conditions
90+ # Use a single global lock file in HF cache directory to serialize loads.
8291 lock_path = Path (HF_MODULES_CACHE ) / "_remote_code.lock"
83-
84- # Create and acquire the lock
8592 lock = filelock .FileLock (str (lock_path ), timeout = timeout )
8693
94+ # Guard only acquisition so caller-body exceptions propagate (single-yield).
8795 try :
88- with lock :
89- yield
90- except (PermissionError , OSError , filelock .Timeout ) as e :
91- # Fallback to tempdir when primary lock path is unusable (e.g.,
92- # NFS locking failures like ENOLCK/ESTALE, permission issues,
93- # or lock acquisition timeouts)
94- if isinstance (e ,
95- OSError ) and e .errno not in (errno .EACCES , errno .EPERM ,
96- errno .ENOLCK , errno .ESTALE ):
96+ lock .acquire (timeout = timeout )
97+ except filelock .Timeout :
98+ # Contention, not broken infra: a tempdir lock can't serialize against
99+ # the holder, so degrade to no lock instead of crashing the process.
100+ logger .warning (
101+ f"could not acquire config lock within { timeout } s, proceeding without lock"
102+ )
103+ yield
104+ except (PermissionError , OSError ) as e :
105+ # Broken lock infra (perms / NFS ENOLCK/ESTALE): retry on a tempdir lock.
106+ if not _is_lock_infra_error (e ):
97107 raise
98108 tmp_dir = Path (tempfile .gettempdir ())
99109 tmp_dir .mkdir (parents = True , exist_ok = True )
100- tmp_lock_path = tmp_dir / "_remote_code.lock"
101- tmp_lock = filelock . FileLock ( str ( tmp_lock_path ), timeout = timeout )
110+ tmp_lock = filelock . FileLock ( str ( tmp_dir / "_remote_code.lock" ),
111+ timeout = timeout )
102112 try :
103- with tmp_lock :
104- yield
105- except filelock .Timeout :
113+ tmp_lock .acquire (timeout = timeout )
114+ except (PermissionError , OSError , filelock .Timeout ):
106115 logger .warning (
107- f"failed to acquire tempdir config lock within { timeout } seconds, proceeding without lock"
108- )
109- # proceed without lock
116+ "tempdir config lock unavailable, proceeding without lock" )
110117 yield
111- except (PermissionError , OSError ) as e :
112- if isinstance (
113- e , OSError ) and e .errno not in (errno .EACCES , errno .EPERM ,
114- errno .ENOLCK , errno .ESTALE ):
115- raise
116- logger .warning (
117- f"tempdir config lock unavailable due to OS/permission issue: { e } , proceeding without lock"
118- )
119- # proceed without lock
118+ else :
119+ try :
120+ yield
121+ finally :
122+ tmp_lock .release ()
123+ else :
124+ try :
120125 yield
126+ finally :
127+ lock .release ()
121128
122129
123130@dataclass (kw_only = True )
0 commit comments