Skip to content

Commit

Permalink
Merge pull request #39477 from dashpole/zombie_wc
Browse files Browse the repository at this point in the history
Automatic merge from submit-queue (batch tested with PRs 39486, 37288, 39477, 39455, 39542)

Fix wc zombie goroutine issue in volume util

See [Cadvisor #1558](google/cadvisor#1558).  This should solve problems for those using images that do not support "wc".
cc: @timstclair
  • Loading branch information
Kubernetes Submit Queue authored Jan 10, 2017
2 parents dd544bb + 094cfd7 commit c03ec46
Showing 1 changed file with 19 additions and 26 deletions.
45 changes: 19 additions & 26 deletions pkg/volume/util/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"bytes"
"fmt"
"os/exec"
"strconv"
"strings"
"syscall"

Expand Down Expand Up @@ -69,35 +68,29 @@ func Du(path string) (*resource.Quantity, error) {
return &used, nil
}

// Find uses the command `find <path> -dev -printf '.' | wc -c` to count files and directories.
// Find uses the equivalent of the command `find <path> -dev -printf '.' | wc -c` to count files and directories.
// While this is not an exact measure of inodes used, it is a very good approximation.
func Find(path string) (int64, error) {
var stdout, stdwcerr, stdfinderr bytes.Buffer
var err error
if path == "" {
return 0, fmt.Errorf("invalid directory")
}
var counter byteCounter
var stderr bytes.Buffer
findCmd := exec.Command("find", path, "-xdev", "-printf", ".")
wcCmd := exec.Command("wc", "-c")
if wcCmd.Stdin, err = findCmd.StdoutPipe(); err != nil {
return 0, fmt.Errorf("failed to setup stdout for cmd %v - %v", findCmd.Args, err)
findCmd.Stdout, findCmd.Stderr = &counter, &stderr
if err := findCmd.Start(); err != nil {
return 0, fmt.Errorf("failed to exec cmd %v - %v; stderr: %v", findCmd.Args, err, stderr.String())
}
wcCmd.Stdout, wcCmd.Stderr, findCmd.Stderr = &stdout, &stdwcerr, &stdfinderr
if err = findCmd.Start(); err != nil {
return 0, fmt.Errorf("failed to exec cmd %v - %v; stderr: %v", findCmd.Args, err, stdfinderr.String())
if err := findCmd.Wait(); err != nil {
return 0, fmt.Errorf("cmd %v failed. stderr: %s; err: %v", findCmd.Args, stderr.String(), err)
}
return counter.bytesWritten, nil
}

if err = wcCmd.Start(); err != nil {
return 0, fmt.Errorf("failed to exec cmd %v - %v; stderr %v", wcCmd.Args, err, stdwcerr.String())
}
err = findCmd.Wait()
if err != nil {
return 0, fmt.Errorf("cmd %v failed. stderr: %s; err: %v", findCmd.Args, stdfinderr.String(), err)
}
err = wcCmd.Wait()
if err != nil {
return 0, fmt.Errorf("cmd %v failed. stderr: %s; err: %v", wcCmd.Args, stdwcerr.String(), err)
}
inodeUsage, err := strconv.ParseInt(strings.TrimSpace(stdout.String()), 10, 64)
if err != nil {
return 0, fmt.Errorf("cannot parse cmds: %v, %v output %s - %s", findCmd.Args, wcCmd.Args, stdout.String(), err)
}
return inodeUsage, nil
// Simple io.Writer implementation that counts how many bytes were written.
type byteCounter struct{ bytesWritten int64 }

func (b *byteCounter) Write(p []byte) (int, error) {
b.bytesWritten += int64(len(p))
return len(p), nil
}

0 comments on commit c03ec46

Please sign in to comment.