5050 # slot. Shared holders then coexist, and neither kind overlaps an exclusive
5151 # one. Locking past the end of the file is allowed.
5252 _SHARED_SLOTS = 64
53+ # Windows locks are mandatory, so the exclusive holder writes its PID past
54+ # the locked bytes, where a refused contender can still read it.
55+ _PID_OFFSET = 1 + _SHARED_SLOTS
5356
5457 def _lock_range (fh : IO , start : int , length : int ) -> bool :
5558 try :
@@ -76,6 +79,8 @@ def _unlock(fh: IO) -> None:
7679else :
7780 import fcntl
7881
82+ _PID_OFFSET = 0
83+
7984 def _try_lock (fh : IO , shared : bool = False ) -> bool :
8085 try :
8186 mode = fcntl .LOCK_SH if shared else fcntl .LOCK_EX
@@ -168,11 +173,12 @@ def release(self) -> None:
168173 def holder_pid (self ) -> Optional [int ]:
169174 """PID left in the lock file by the current exclusive holder, if any.
170175
171- Best effort: Windows refuses to read a locked byte range, and a shared
172- holder records nothing (there may be several).
176+ Best effort: a shared holder records nothing (there may be several).
173177 """
174178 try :
175- text = self .path .read_text ().strip ()
179+ with open (self .path , "rb" ) as fh :
180+ fh .seek (_PID_OFFSET )
181+ text = fh .read ().decode ("ascii" , "replace" ).strip ()
176182 except OSError :
177183 return None
178184 return int (text ) if text .isdigit () else None
@@ -183,7 +189,7 @@ def _record_holder(self, shared: bool) -> None:
183189 self ._clear_holder ()
184190 if not shared :
185191 try :
186- self ._fh .write (str (os .getpid ()))
192+ self ._fh .write (" " * _PID_OFFSET + str (os .getpid ()))
187193 self ._fh .flush ()
188194 except OSError :
189195 pass
0 commit comments