Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go-fuse
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go-fuse
Commits
c1a4d6c4
Commit
c1a4d6c4
authored
Nov 12, 2023
by
Han-Wen Nienhuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fs: describe one more deadlock scenario
Change-Id: I43f09613acd119daefe64350a46f79d58b2e4b6a
parent
5b76a74a
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
33 additions
and
18 deletions
+33
-18
fs/api.go
fs/api.go
+33
-18
No files found.
fs/api.go
View file @
c1a4d6c4
...
@@ -145,14 +145,30 @@
...
@@ -145,14 +145,30 @@
// threads, and makes assumptions that some system calls do not
// threads, and makes assumptions that some system calls do not
// block. When accessing a file system from the same process that
// block. When accessing a file system from the same process that
// serves the file system (e.g. in unittests), this can lead to
// serves the file system (e.g. in unittests), this can lead to
// deadlocks, especially when GOMAXPROCS=1. The following deadlocks
// deadlocks, especially when GOMAXPROCS=1, when the Go runtime
// are known:
// assumes a system call does not block, but actually is served by the
// Go-FUSE process.
//
//
// 1. Spawning a subprocess uses a fork/exec sequence. In this
// The following deadlocks are known:
// sequence, the child process uses dup3() to remap file
//
// descriptors. If the destination fd happens to be backed by Go-FUSE,
// 1. Spawning a subprocess uses a fork/exec sequence: the process
// the dup3() call will implicitly close the fd, generating a FLUSH
// forks itself into a parent and child. The parent waits for the
// operation. If there is no thread left to respond, the process is deadlocked.
// child to signal that the exec failed or succeeded, while the child
// prepares for calling exec(). Any setup step in the child that
// triggers a FUSE request can cause a deadlock.
//
// 1a. If the subprocess has a directory specified, the child will
// chdir into that directory. This generates an ACCESS operation on
// the directory.
//
// This deadlock can be avoided by disabling the ACCESS
// operation: return syscall.ENOSYS in the Access implementation, and
// ensure it is triggered called before initiating the subprocess.
//
// 1b. If the subprocess inherits files, the child process uses dup3()
// to remap file descriptors. If the destination fd happens to be
// backed by Go-FUSE, the dup3() call will implicitly close the fd,
// generating a FLUSH operation, eg.
//
//
// f1, err := os.Open("/fusemnt/file1")
// f1, err := os.Open("/fusemnt/file1")
// // f1.Fd() == 3
// // f1.Fd() == 3
...
@@ -164,9 +180,10 @@
...
@@ -164,9 +180,10 @@
// // f2 (fd 4) is moved to fd 3. Deadlocks with GOMAXPROCS=1.
// // f2 (fd 4) is moved to fd 3. Deadlocks with GOMAXPROCS=1.
// cmd.Start()
// cmd.Start()
//
//
// This can be avoided by ensuring that file descriptors pointing into
// This deadlock can be avoided by ensuring that file descriptors
// FUSE mounts and file descriptors passed into subprocesses do not
// pointing into FUSE mounts and file descriptors passed into
// overlap, e.g. inserting the following before the above example:
// subprocesses do not overlap, e.g. inserting the following before
// the above example:
//
//
// for {
// for {
// f, _ := os.Open("/dev/null")
// f, _ := os.Open("/dev/null")
...
@@ -176,14 +193,12 @@
...
@@ -176,14 +193,12 @@
// }
// }
// }
// }
//
//
// 2. The Go runtime uses the epoll system call to schedule
// 2. The Go runtime uses the epoll system call to understand which
// goroutines, and assumes that epoll does not block. However, the
// goroutines can respond to I/O. The runtime assumes that epoll does
// FUSE kernel module implements the POLL opcode. If the Go runtime
// not block, but if files are on a FUSE filesystem, the kernel will
// calls epoll() with files opened on a FUSE mount, and if there is
// generate a POLL operation. To prevent this from happening, Go-FUSE
// only one thread available for execution, there is no thread left to
// disables the POLL opcode on mount. To ensure this has happened, call
// respond to the POLL opcode, leading to deadlock. To prevent this
// WaitMount.
// from happening, Go-FUSE centrally disables the POLL opcode. (See
// commit 4f10e248ebabd3cdf9c0aa3ae58fd15235f82a79)
//
//
// # Dynamically discovered file systems
// # Dynamically discovered file systems
//
//
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment