summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2019-02-17 14:44:29 -0800
committerZac Medico <zmedico@gentoo.org>2019-02-17 15:02:48 -0800
commit34532af167cff457c3cccda4ea4249a0bc26481a (patch)
tree1f623ba8151ba2a476b8d509214286d11237ec3b
parentutil: fix whitespace bug introduced in cleanup of get_cpu_count work (diff)
downloadportage-34532af167cff457c3cccda4ea4249a0bc26481a.tar.gz
portage-34532af167cff457c3cccda4ea4249a0bc26481a.tar.bz2
portage-34532af167cff457c3cccda4ea4249a0bc26481a.zip
locks: handle sshfs hardlink inode numbers (bug 678218)
Since hardlinks on sshfs do not have matching inode numbers, detect this behavior and use a simple stat call to detect if lock_path has been removed. Bug: https://bugs.gentoo.org/678218 Signed-off-by: Zac Medico <zmedico@gentoo.org>
-rw-r--r--lib/portage/locks.py27
1 files changed, 27 insertions, 0 deletions
diff --git a/lib/portage/locks.py b/lib/portage/locks.py
index 74c2c086a..510925da0 100644
--- a/lib/portage/locks.py
+++ b/lib/portage/locks.py
@@ -340,6 +340,33 @@ def _lockfile_was_removed(lock_fd, lock_path):
hardlink_stat = os.stat(hardlink_path)
if hardlink_stat.st_ino != fstat_st.st_ino or hardlink_stat.st_dev != fstat_st.st_dev:
+ # Create another hardlink in order to detect whether or not
+ # hardlink inode numbers are expected to match. For example,
+ # inode numbers are not expected to match for sshfs.
+ inode_test = hardlink_path + '-inode-test'
+ try:
+ os.unlink(inode_test)
+ except OSError as e:
+ if e.errno not in (errno.ENOENT, errno.ESTALE):
+ _raise_exc(e)
+ try:
+ os.link(hardlink_path, inode_test)
+ except OSError as e:
+ if e.errno not in (errno.ENOENT, errno.ESTALE):
+ _raise_exc(e)
+ return True
+ 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)
+ finally:
+ try:
+ os.unlink(inode_test)
+ except OSError as e:
+ if e.errno not in (errno.ENOENT, errno.ESTALE):
+ _raise_exc(e)
return True
finally:
try: