diff options
author | Peri <peri@srdi.org> | 2023-05-11 02:38:46 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-11 02:38:46 +0100 |
commit | bb1890afd7d1eb33e95f36d1d9936dbd574260b6 (patch) | |
tree | 9c5d13d913e6dcd0fab15b8970c8805620305e81 /test/test_examples.py | |
parent | fcd293f675fc7bfa0522186c5d68ef932eec6945 (diff) | |
download | fuse-bb1890afd7d1eb33e95f36d1d9936dbd574260b6.tar.gz |
Fix issue #746. (#782)
Added a secondary check in fuse_lib_unlink() after hide_node()
to check again under a lock if the (now hidden) file is still open.
If not then delete it.
This should synchronise fuse_lib_unlink() with fuse_lib_release(),
when nullpath_ok is set.
Diffstat (limited to 'test/test_examples.py')
-rwxr-xr-x | test/test_examples.py | 59 |
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) |