commit: 59e9452fda79f69e9b5ab7e44ef918f6fb4d6161 Author: Zac Medico <zmedico <AT> gentoo <DOT> org> AuthorDate: Wed Mar 25 05:11:06 2020 +0000 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> CommitDate: Wed Mar 25 07:24:52 2020 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=59e9452f
_lockfile_was_removed: return fstat result (bug 714480) Return a tuple that includes the fstat result, which can be used to detect when there's an attempt to lock the same inode more than once by the same process, since in that case the lock will not behave as intended with the default fcntl.lockf function. Bug: https://bugs.gentoo.org/714480 Signed-off-by: Zac Medico <zmedico <AT> gentoo.org> lib/portage/locks.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/portage/locks.py b/lib/portage/locks.py index 72ac2fc70..7bb0542dd 100644 --- a/lib/portage/locks.py +++ b/lib/portage/locks.py @@ -296,10 +296,9 @@ def _lockfile_iteration(mypath, wantnewlockfile=False, unlinkfile=False, else: raise - if isinstance(lockfilename, basestring) and myfd != HARDLINK_FD and unlinkfile: try: - removed = _lockfile_was_removed(myfd, lockfilename) + (removed, fstat_result) = _lockfile_was_removed(myfd, lockfilename) except Exception: # Do not leak the file descriptor here. os.close(myfd) @@ -341,14 +340,15 @@ def _lockfile_was_removed(lock_fd, lock_path): @param lock_path: path of lock file @type lock_path: str @rtype: bool - @return: True if lock_path exists and corresponds to lock_fd, False otherwise + @return: a tuple of (removed, fstat_result), where removed is True if + lock_path does not correspond to lock_fd, and False otherwise """ try: fstat_st = os.fstat(lock_fd) except OSError as e: if e.errno not in (errno.ENOENT, errno.ESTALE): _raise_exc(e) - return True + return (True, None) # Since stat is not reliable for removed files on NFS with the default # file attribute cache behavior ('ac' mount option), create a temporary @@ -365,7 +365,7 @@ def _lockfile_was_removed(lock_fd, lock_path): except OSError as e: if e.errno not in (errno.ENOENT, errno.ESTALE): _raise_exc(e) - return True + return (True, None) hardlink_stat = os.stat(hardlink_path) if hardlink_stat.st_ino != fstat_st.st_ino or hardlink_stat.st_dev != fstat_st.st_dev: @@ -383,13 +383,13 @@ def _lockfile_was_removed(lock_fd, lock_path): except OSError as e: if e.errno not in (errno.ENOENT, errno.ESTALE): _raise_exc(e) - return True + return (True, None) else: if not os.path.samefile(hardlink_path, inode_test): # This implies that inode numbers are not expected # to match for this file system, so use a simple # stat call to detect if lock_path has been removed. - return not os.path.exists(lock_path) + return (not os.path.exists(lock_path), fstat_st) finally: try: os.unlink(inode_test) @@ -403,7 +403,7 @@ def _lockfile_was_removed(lock_fd, lock_path): except OSError as e: if e.errno not in (errno.ENOENT, errno.ESTALE): _raise_exc(e) - return False + return (False, fstat_st) def _fstat_nlink(fd):
