@@ -13,9 +13,8 @@ import (
13
13
)
14
14
15
15
func (fh * FuseHost ) detectFuseStarted (ctx context.Context , started chan error ) {
16
- time .Sleep (100 * time .Millisecond )
17
- var st unix.Stat_t
18
- if err := unix .Stat (fh .mountPoint , & st ); err != nil {
16
+ st , err := statWithTimeout (ctx , fh .mountPoint , 10 * time .Millisecond )
17
+ if err != nil {
19
18
select {
20
19
case started <- fmt .Errorf ("unable to stat mount point %q: %v" , fh .mountPoint , err ):
21
20
default :
@@ -39,8 +38,7 @@ func (fh *FuseHost) detectFuseStarted(ctx context.Context, started chan error) {
39
38
}
40
39
return
41
40
case <- ticker .C :
42
- var mountSt unix.Stat_t
43
- if err := unix .Stat (fh .mountPoint , & mountSt ); err != nil {
41
+ if mountSt , err := statWithTimeout (ctx , fh .mountPoint , 20 * time .Millisecond ); err != nil {
44
42
// we don't consider a failure to stat an error here, just a cause for a retry.
45
43
logrus .Debugf ("unable to stat mount point %q: %v" , fh .mountPoint , err )
46
44
} else {
@@ -51,3 +49,24 @@ func (fh *FuseHost) detectFuseStarted(ctx context.Context, started chan error) {
51
49
}
52
50
}
53
51
}
52
+
53
+ // statWithTimeout performs a normal unix.Stat but will not allow that it hangs for
54
+ // more than the given timeout.
55
+ func statWithTimeout (ctx context.Context , path string , timeout time.Duration ) (* unix.Stat_t , error ) {
56
+ ctx , cancel := context .WithTimeout (ctx , timeout )
57
+ defer cancel ()
58
+ errCh := make (chan error , 1 )
59
+ mountSt := new (unix.Stat_t )
60
+ go func () {
61
+ errCh <- unix .Stat (path , mountSt )
62
+ }()
63
+ select {
64
+ case <- ctx .Done ():
65
+ return nil , ctx .Err ()
66
+ case err := <- errCh :
67
+ if err != nil {
68
+ return nil , err
69
+ }
70
+ return mountSt , nil
71
+ }
72
+ }
0 commit comments