Skip to content

Instantly share code, notes, and snippets.

@jameshartig
Last active August 18, 2020 19:53
Show Gist options
  • Save jameshartig/756f67d406540ad8ae14d22e651043d0 to your computer and use it in GitHub Desktop.
Save jameshartig/756f67d406540ad8ae14d22e651043d0 to your computer and use it in GitHub Desktop.
reproduction of golang/go#40846
package main
import (
"context"
"fmt"
"math/rand"
"os"
"os/signal"
"syscall"
"time"
"bazil.org/fuse"
"bazil.org/fuse/fs"
)
type testFS struct {
}
// Root implements the fuse.FS interface
func (f *testFS) Root() (fs.Node, error) {
return &testFSRoot{}, nil
}
type testFSRoot struct {
}
var _ fs.Node = (*testFSRoot)(nil)
// Attr implements the fs.Node interface
func (n *testFSRoot) Attr(_ context.Context, dest *fuse.Attr) error {
dest.Mode |= 0755 | os.ModeDir
dest.Inode = 1
dest.Valid = 0
return nil
}
var _ fs.NodeGetattrer = (*testFSRoot)(nil)
// Getattr implements the fs.NodeGetattrer interface
func (n *testFSRoot) Getattr(ctx context.Context, req *fuse.GetattrRequest, resp *fuse.GetattrResponse) error {
select {
case <-ctx.Done():
fmt.Printf("interrrupted %v\n", req.ID)
return ctx.Err()
case <-time.After(time.Duration(rand.Intn(5)) * time.Second):
}
return n.Attr(ctx, &resp.Attr)
}
func main() {
err := os.MkdirAll("./test", 0755)
if err != nil {
panic(err)
}
fuse.Debug = func(msg interface{}) {
fmt.Printf("fuse: %v\n", msg)
}
fuseOpts := []fuse.MountOption{
fuse.AllowNonEmptyMount(), // allow shadowing existing folders
fuse.AsyncRead(), // allow simultaneous reads
fuse.DefaultPermissions(), // use the chmod permissions
}
fuseConn, err := fuse.Mount("./test", fuseOpts...)
if err != nil {
panic(err)
}
go func() {
err := fs.Serve(fuseConn, &testFS{})
if err != nil {
panic(err)
}
}()
stopCh := make(chan struct{})
go func() {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGUSR2)
t := time.Tick(100 * time.Microsecond)
for {
select {
case <-stopCh:
return
case <-t:
}
syscall.Kill(0, syscall.SIGUSR2)
<-c
}
}()
for i := 0; i < 10; i++ {
_, err := os.Stat("./test")
if err != nil {
fmt.Printf("error: %v\n", err)
break
}
time.Sleep(100 * time.Millisecond)
}
close(stopCh)
for {
err := fuse.Unmount("./test")
if err == nil {
return
}
fmt.Println("unmount error", err)
time.Sleep(time.Second)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment