summaryrefslogtreecommitdiff
path: root/test/test_examples.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_examples.py')
-rwxr-xr-xtest/test_examples.py59
1 files changed, 59 insertions, 0 deletions
diff --git a/test/test_examples.py b/test/test_examples.py
index f0aa63d..958e633 100755
--- a/test/test_examples.py
+++ b/test/test_examples.py
@@ -442,6 +442,65 @@ def test_cuse(output_checker):
finally:
mount_process.terminate()
+def test_release_unlink_race(tmpdir, output_checker):
+ """test case for Issue #746
+
+ If RELEASE and UNLINK opcodes are sent back to back, and fuse_fs_release()
+ and fuse_fs_rename() are slow to execute, UNLINK will run while RELEASE is
+ still executing. UNLINK will try to rename the file and, while the rename
+ is happening, the RELEASE will finish executing. As a result, RELEASE will
+ not detect in time that UNLINK has happened, and UNLINK will not detect in
+ time that RELEASE has happened.
+
+
+ NOTE: This is triggered only when nullpath_ok is set.
+
+ If it is NOT SET then get_path_nullok() called by fuse_lib_release() will
+ call get_path_common() and lock the path, and then the fuse_lib_unlink()
+ will wait for the path to be unlocked before executing and thus synchronise
+ with fuse_lib_release().
+
+ If it is SET then get_path_nullok() will just set the path to null and
+ return without locking anything and thus allowing fuse_lib_unlink() to
+ eventually execute unimpeded while fuse_lib_release() is still running.
+ """
+
+ fuse_mountpoint = str(tmpdir)
+
+ fuse_binary_command = base_cmdline + \
+ [ pjoin(basename, 'test', 'release_unlink_race'),
+ "-f", fuse_mountpoint]
+
+ fuse_process = subprocess.Popen(fuse_binary_command,
+ stdout=output_checker.fd,
+ stderr=output_checker.fd)
+
+ try:
+ wait_for_mount(fuse_process, fuse_mountpoint)
+
+ temp_dir = tempfile.TemporaryDirectory(dir="/tmp/")
+ temp_dir_path = temp_dir.name
+
+ fuse_temp_file, fuse_temp_file_path = tempfile.mkstemp(dir=(fuse_mountpoint + temp_dir_path))
+
+ os.close(fuse_temp_file)
+ os.unlink(fuse_temp_file_path)
+
+ # needed for slow CI/CD pipelines for unlink OP to complete processing
+ safe_sleep(3)
+
+ assert os.listdir(temp_dir_path) == []
+
+ except:
+ temp_dir.cleanup()
+ cleanup(fuse_process, fuse_mountpoint)
+ raise
+
+ else:
+ temp_dir.cleanup()
+ umount(fuse_process, fuse_mountpoint)
+
+
@contextmanager
def os_open(name, flags):
fd = os.open(name, flags)