Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lock acquire blocks indefinitely if directory name in path changes #60

Closed
mcsimps2 opened this issue Feb 6, 2020 · 1 comment
Closed

Comments

@mcsimps2
Copy link

mcsimps2 commented Feb 6, 2020

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
@mcsimps2
Copy link
Author

mcsimps2 commented Feb 6, 2020

Just saw this was solved by #47

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant