1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
|
// Copyright 2019 the Go-FUSE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package fs
import (
"context"
"os/exec"
"syscall"
"testing"
"time"
"github.com/hanwen/go-fuse/v2/fuse"
)
type interruptRoot struct {
Inode
child interruptOps
}
var _ = (NodeLookuper)((*interruptRoot)(nil))
func (r *interruptRoot) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, syscall.Errno) {
if name != "file" {
return nil, syscall.ENOENT
}
ch := r.Inode.NewInode(ctx, &r.child, StableAttr{
Ino: 2,
Gen: 1})
return ch, OK
}
type interruptOps struct {
Inode
interrupted bool
}
var _ = (NodeOpener)((*interruptOps)(nil))
func (o *interruptOps) Open(ctx context.Context, flags uint32) (FileHandle, uint32, syscall.Errno) {
select {
case <-time.After(100 * time.Millisecond):
return nil, 0, syscall.EIO
case <-ctx.Done():
o.interrupted = true
return nil, 0, syscall.EINTR
}
}
// This currently doesn't test functionality, but is useful to investigate how
// INTERRUPT opcodes are handled.
func TestInterrupt(t *testing.T) {
root := &interruptRoot{}
oneSec := time.Second
mntDir, _, clean := testMount(t, root, &Options{
EntryTimeout: &oneSec,
AttrTimeout: &oneSec,
})
defer func() {
if clean != nil {
clean()
}
}()
cmd := exec.Command("cat", mntDir+"/file")
if err := cmd.Start(); err != nil {
t.Fatalf("run %v: %v", cmd, err)
}
time.Sleep(10 * time.Millisecond)
if err := cmd.Process.Kill(); err != nil {
t.Errorf("Kill: %v", err)
}
clean()
clean = nil
if !root.child.interrupted {
t.Errorf("open request was not interrupted")
}
}
|