Commit 8e0bbdb1 authored by Jakob Unterwurzacher's avatar Jakob Unterwurzacher Committed by Han-Wen Nienhuys

fuse: fix deadlock in TestCacheControl, update docs

This test mmap()s a file, which means reading the
memory can block, triggering file I/O and FUSE requests.
With GOMAXPROCS=1, we don't have a free thread to handle
those requests, deadlocking the test:

	GOMAXPROCS=1 go test -v -count=1 -run TestCacheControl ./fuse/test

Use mlock() to fix that, also add a warning to the
"fuse" package docs.

Fixes https://github.com/hanwen/go-fuse/issues/261

Change-Id: Ia32fb1826c2be602cf4f0f6cf73956af797c940c
parent e29d3106
...@@ -67,6 +67,12 @@ ...@@ -67,6 +67,12 @@
// Typically, each call of the API happens in its own // Typically, each call of the API happens in its own
// goroutine, so take care to make the file system thread-safe. // goroutine, so take care to make the file system thread-safe.
// //
// Be careful when you access the FUSE mount from the same process. An access can
// tie up two OS threads (one on the request side and one on the FUSE server side).
// This can deadlock if there is no free thread to handle the FUSE server side.
// Run your program with GOMAXPROCS=1 to make the problem easier to reproduce,
// see https://github.com/hanwen/go-fuse/issues/261 for an example of that
// problem.
// //
// Higher level interfaces // Higher level interfaces
// //
......
...@@ -189,11 +189,19 @@ func TestCacheControl(t *testing.T) { ...@@ -189,11 +189,19 @@ func TestCacheControl(t *testing.T) {
defer func() { defer func() {
xmunmap(fmmap) xmunmap(fmmap)
}() }()
xmlock(fmmap)
// assertMmapRead asserts that file's mmaped memory reads as dataOK. // assertMmapRead asserts that file's mmaped memory reads as dataOK.
assertMmapRead := func(subj, dataOK string) { assertMmapRead := func(subj, dataOK string) {
t.Helper() t.Helper()
// Use the Mlock() syscall to get the mmap'ed range into the kernel
// cache again, triggering FUSE reads as neccessary. A blocked syscall does
// not count towards GOMAXPROCS, so there should be a thread available
// to handle the FUSE reads.
// If we don't Mlock() first, the memory comparison triggers a page
// fault, which blocks the thread, and deadlocks the test reliably at
// GOMAXPROCS=1.
// Fixes https://github.com/hanwen/go-fuse/issues/261 .
xmlock(fmmap)
if string(fmmap) != dataOK { if string(fmmap) != dataOK {
t.Fatalf("%s: file mmap: got %q ; want %q", subj, fmmap, dataOK) t.Fatalf("%s: file mmap: got %q ; want %q", subj, fmmap, dataOK)
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment