Skip to content

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

@mcsimps2

Description

@mcsimps2

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions