diff --git a/samples/mount_sample/mount.go b/samples/mount_sample/mount.go index 48f860d..e7d0def 100644 --- a/samples/mount_sample/mount.go +++ b/samples/mount_sample/mount.go @@ -17,6 +17,7 @@ package main import ( + "errors" "flag" "fmt" "log" @@ -30,6 +31,7 @@ import ( var fType = flag.String("type", "", "The name of the samples/ sub-dir.") var fMountPoint = flag.String("mount_point", "", "Path to mount point.") +var fReadyFile = flag.Uint64("ready_file", 0, "FD to signal when ready.") var fFlushesFile = flag.Uint64("flushfs.flushes_file", 0, "") var fFsyncsFile = flag.Uint64("flushfs.fsyncs_file", 0, "") @@ -97,9 +99,25 @@ func makeFS() (fs fuse.FileSystem, err error) { return } +func getReadyFile() (f *os.File, err error) { + if *fReadyFile == 0 { + err = errors.New("You must set --ready_file.") + return + } + + f = os.NewFile(uintptr(*fReadyFile), "(ready file)") + return +} + func main() { flag.Parse() + // Grab the file to signal when ready. + readyFile, err := getReadyFile() + if err != nil { + log.Fatalf("getReadyFile:", err) + } + // Create an appropriate file system. fs, err := makeFS() if err != nil { @@ -121,6 +139,12 @@ func main() { log.Fatalf("WaitForReady: %v", err) } + // Signal that it is ready. + _, err = readyFile.Write([]byte("x")) + if err != nil { + log.Fatalf("readyFile.Write: %v", err) + } + // Wait for it to be unmounted. if err = mfs.Join(context.Background()); err != nil { log.Fatalf("Join: %v", err) diff --git a/samples/subprocess.go b/samples/subprocess.go index fcfbcdd..acfd97d 100644 --- a/samples/subprocess.go +++ b/samples/subprocess.go @@ -24,7 +24,6 @@ import ( "os/exec" "path" "sync" - "time" "github.com/jacobsa/ogletest" "golang.org/x/net/context" @@ -145,6 +144,16 @@ func waitForMountSample( err = fmt.Errorf("Waiting for mount_sample: %v", err) } +func waitForReady(readyReader *os.File, c chan<- struct{}) { + _, err := readyReader.Read(make([]byte, 1)) + if err != nil { + log.Printf("Readying from ready pipe: %v", err) + return + } + + c <- struct{}{} +} + // Like SetUp, but doens't panic. func (t *SubprocessTest) initialize() (err error) { // Initialize the context. @@ -174,6 +183,18 @@ func (t *SubprocessTest) initialize() (err error) { args = append(args, t.MountFlags...) + // Set up a pipe for the "ready" status. + readyReader, readyWriter, err := os.Pipe() + if err != nil { + err = fmt.Errorf("Pipe: %v", err) + return + } + + defer readyReader.Close() + defer readyWriter.Close() + + t.MountFiles["ready_file"] = readyWriter + // Set up inherited files and appropriate flags. var extraFiles []*os.File for flag, file := range t.MountFiles { @@ -199,12 +220,21 @@ func (t *SubprocessTest) initialize() (err error) { // Launch a goroutine that waits for it and returns its status. mountSampleErr := make(chan error, 1) - t.mountSampleErr = mountSampleErr go waitForMountSample(mountCmd, mountSampleErr, &stderr) - // TODO(jacobsa): Probably need some sort of signalling (on stderr? write to - // a flag-controlled file?) when WaitForReady has returned. - time.Sleep(time.Second) + // Wait for the tool to say the file system is ready. In parallel, watch for + // the tool to fail. + readyChan := make(chan struct{}, 1) + go waitForReady(readyReader, readyChan) + + select { + case <-readyChan: + case err = <-mountSampleErr: + return + } + + // TearDown is no responsible for joining. + t.mountSampleErr = mountSampleErr return }