@@ -19,6 +19,7 @@ import (
19
19
"os"
20
20
"path/filepath"
21
21
"runtime"
22
+ "sync"
22
23
)
23
24
24
25
// traverseLink is a sentinel error for fastWalk, similar to filepath.SkipDir.
@@ -48,6 +49,13 @@ func fastWalk(root string, walkFn func(path string, typ os.FileMode) error) erro
48
49
if n := runtime .NumCPU (); n > numWorkers {
49
50
numWorkers = n
50
51
}
52
+
53
+ // Make sure to wait for all workers to finish, otherwise
54
+ // walkFn could still be called after returning. This Wait call
55
+ // runs after close(e.donec) below.
56
+ var wg sync.WaitGroup
57
+ defer wg .Wait ()
58
+
51
59
w := & walker {
52
60
fn : walkFn ,
53
61
enqueuec : make (chan walkItem , numWorkers ), // buffered for performance
@@ -58,9 +66,10 @@ func fastWalk(root string, walkFn func(path string, typ os.FileMode) error) erro
58
66
resc : make (chan error , numWorkers ),
59
67
}
60
68
defer close (w .donec )
61
- // TODO(bradfitz): start the workers as needed? maybe not worth it.
69
+
62
70
for i := 0 ; i < numWorkers ; i ++ {
63
- go w .doWork ()
71
+ wg .Add (1 )
72
+ go w .doWork (& wg )
64
73
}
65
74
todo := []walkItem {{dir : root }}
66
75
out := 0
@@ -103,13 +112,18 @@ func fastWalk(root string, walkFn func(path string, typ os.FileMode) error) erro
103
112
104
113
// doWork reads directories as instructed (via workc) and runs the
105
114
// user's callback function.
106
- func (w * walker ) doWork () {
115
+ func (w * walker ) doWork (wg * sync.WaitGroup ) {
116
+ defer wg .Done ()
107
117
for {
108
118
select {
109
119
case <- w .donec :
110
120
return
111
121
case it := <- w .workc :
112
- w .resc <- w .walk (it .dir , ! it .callbackDone )
122
+ select {
123
+ case <- w .donec :
124
+ return
125
+ case w .resc <- w .walk (it .dir , ! it .callbackDone ):
126
+ }
113
127
}
114
128
}
115
129
}
@@ -157,6 +171,7 @@ func (w *walker) onDirEnt(dirName, baseName string, typ os.FileMode) error {
157
171
}
158
172
return err
159
173
}
174
+
160
175
func (w * walker ) walk (root string , runUserCallback bool ) error {
161
176
if runUserCallback {
162
177
err := w .fn (root , os .ModeDir )
0 commit comments