macos-fuse-t/fuse-t

Unclosed file descriptors on demonization

Closed this issue · 10 comments

xaizek commented

I think that this issue with using fuse-zip built against fuse-t is caused by fuse-t not closing stderr (and maybe other descriptors) during demonization. Vifm efectively waits for data on stderr from a zombie, so the likely explanation is that zombie's child keeps the descriptor open. So please verify how you demonize and fix it if my guess is right.

alexfs commented

Do you have instructions how to build vifm with fuse-t and provide configuration instructions so I can test ?

xaizek commented

Vifm doesn't link against fuse-t. It just invokes fuse-zip and waits for it to finish by reading its error stream. The issue manifests with v0.13, earlier versions just appended somethinig like 2>/tmp/fuse.err to FUSE mount command.

Vifm's configuration file is either ~/.config/vifm/vifmrc if ~/.config exists (assuming $XDG_DATA_HOME isn't set) or in ~/.vifm/vifmrc. You only need one line (put it at the top):

filetype *.zip FUSE_MOUNT|fuse-zip %SOURCE_FILE %DESTINATION_DIR

Then run vifm --select path/to/some.zip and press Enter, this should invoke fuse-zip to mount the file and enter mount point on success or hang until you kill fuse-zip. Quit Vifm with :q<Enter>.

Doesn't macFUSE behave the same way?

xaizek commented

Doesn't macFUSE behave the same way?

Just built the same fuse-zip (dropping the top commit) against macFUSE and it works well, while fuse-t version hangs.

@alexfs This hanging can be reproduced in a simpler way. Just try to run any FUSE mount with Golang exec.Command using CombinedOutput(). You'll observe that it hangs waiting on unclosed I/O streams. If you need, I can provide a complete repro code. And the issue is not specific to fuse-zip, I'm observing the same behaviour with bindfs.

BTW, I confirm that this issue does NOT happen with macFUSE.

If you have a sample code that would be great

Assumes that you have bindfs in PATH. Build instructions: mpartel/bindfs#100 (comment)

But as I said, any other FUSE fs should also reproduce the issue.

Run as root (sudo is ok):

package main

import (
	"fmt"
	"os"
	"os/exec"
)

func main() {
	_ = os.Mkdir("a", 755)
	_ = os.Mkdir("b", 755)

	cmd := exec.Command("bindfs", "a", "b")
	out, err := cmd.CombinedOutput() // hangs with fuse-t reading from stdout/stderr, but exits normally with macFUSE
	if err != nil {
		fmt.Printf("%s: %v", string(out), err)
		panic(err)
	}
	println("done")
}

Confirming this is fixed in 1.0.24.

xaizek commented

Didn't notice there was a release. It is indeed fixed. Thanks.