-
-
Notifications
You must be signed in to change notification settings - Fork 118
Description
I have an application whose files may change paths when users rename directories.
For example, a user may rename C:\\...\\Desktop\\MyFolder\\sensitivefile.txt
to C:\\...\\Desktop\\AnotherFolder\\sensitivefile.txt
I've noticed that, at least on Windows, acquiring a file lock in a directory that does not exist (or no longer exists because it was renamed) causes the program to hang indefinitely as it polls infinitely trying to acquire the lock.
fl = FileLock("this\\path\\does\\not\\exist.lock")
with fl:
print("Filelock acquired!")
# Filelock is never acquired, program blocks indefinitely
This can be an issue if a race condition occurs where a user changes the directory name at the right time (which has occurred for me).
Instead of blocking forever, it would be better to throw some sort of error letting the developer know that the path no longer exists, so the lock file can't be created at the specified location.
One proposal: The problem is that we ignore OSError
in the _acquire
method. Instead, we should let FileNotFoundError
propagate as follows:
def _acquire(self):
open_mode = os.O_RDWR | os.O_CREAT | os.O_TRUNC
try:
fd = os.open(self._lock_file, open_mode)
except FileNotFoundError:
# Will err if the path to the parent directory does not exist. If we do not
# raise this here, the acquire() statement will block indefinitely
raise
except OSError:
pass
else:
try:
msvcrt.locking(fd, msvcrt.LK_NBLCK, 1)
except (IOError, OSError):
os.close(fd)
else:
self._lock_file_fd = fd
return None