golang 1.11 os / exec:exec.command内存泄漏问题

时间:2018-11-29 02:26:00

标签: go memory-leaks

我的操作系统环境是MacOS 10.14

我的golang环境是go版本go1.11 darwin / amd64

这是我的简化代码:

import (
    _ "net/http/pprof"
)

var (
    wg sync.WaitGroup
)

func main() {
    go func() {
        http.ListenAndServe(":6060", nil)
    }()
    ticker := time.NewTicker(time.Millisecond * 300)
    c := make(chan os.Signal, 1)
    signal.Notify(c, os.Interrupt, os.Kill)
    for {
        select {
        case <-ticker.C:
            doBan()
        case <-c:
            goto DONE
        }
    }
DONE:
    doBan()
    wg.Wait()
}

func doBan() {
    for i := 0; i < 4; i++ {
        wg.Add(1)
        ips := getIps(i)
        go banIps(ips)
    }
}

func banIps(ips []string) {
    ipset := exec.Command("ipset", "-!", "restore")
    r, w := io.Pipe()
    ipset.Stdin = r
    if err := ipset.Start(); err != nil {
        w.Close()
    } else {
        for _, ip := range (ips) {
            fmt.Fprintf(w, "add ipset %s timeout 3600\n", ip)
        }
        w.Close()
    }

    defer ipset.Wait()
    defer wg.Done()
}

// get lots of ips in real world
func getIps(i int) []string {
    ip := fmt.Sprintf("%d.%d.%d.%d", i, i, i, i)
    return []string{ip}
}

然后我使用go工具pprof来监视内存信息。 http://localhost:6060/debug/pprof/heap?debug=1的结果是这样的:

heap profile: 0: 0 [124: 41696] @ heap/1048576 0: 0 [1: 32] @ 0x10e96b6 0x10e5a67 0x13095a5 0x105d0d1
#   0x10e96b5   os/exec.LookPath+0x1a5 /usr/local/Cellar/go/1.11/libexec/src/os/exec/lp_unix.go:57
#   0x10e5a66   os/exec.Command+0x1b6     /usr/local/Cellar/go/1.11/libexec/src/os/exec/exec.go:161
#   0x13095a4   main.banIps+0x84 /Users/kiyon/Code/github/go/src/github.com/kiyonlin/hello- application/testcmd/main.go:50

0: 0 [3: 96] @ 0x1047d8f 0x104786d 0x1047b07 0x10e0e13 0x10e5657 0x10e53ef 0x10e9662 0x10e5a67 0x13095a5 0x105d0d1
#   0x10e0e12   strings.Join+0x452  /usr/local/Cellar/go/1.11/libexec/src/strings/strings.go:429
#   0x10e5656   path/filepath.join+0xa6 /usr/local/Cellar/go/1.11/libexec/src/path/filepath/path_unix.go:45
#   0x10e53ee   path/filepath.Join+0x3e /usr/local/Cellar/go/1.11/libexec/src/path/filepath/path.go:210
#   0x10e9661   os/exec.LookPath+0x151  /usr/local/Cellar/go/1.11/libexec/src/os/exec/lp_unix.go:52
#   0x10e5a66   os/exec.Command+0x1b6   /usr/local/Cellar/go/1.11/libexec/src/os/exec/exec.go:161
#   0x13095a4   main.banIps+0x84    /Users/kiyon/Code/github/go/src/github.com/kiyonlin/hello-application/testcmd/main.go:50

0: 0 [2: 32] @ 0x1068c56 0x1068d19 0x106e4f9 0x109c93c 0x109c40d 0x10e9489 0x10e9684 0x10e5a67 0x13095a5 0x105d0d1
#   0x1068c55   syscall.ByteSliceFromString+0x95    /usr/local/Cellar/go/1.11/libexec/src/syscall/syscall.go:53
#   0x1068d18   syscall.BytePtrFromString+0x38      /usr/local/Cellar/go/1.11/libexec/src/syscall/syscall.go:69
#   0x106e4f8   syscall.Stat+0x38           /usr/local/Cellar/go/1.11/libexec/src/syscall/zsyscall_darwin_amd64.go:1188
#   0x109c93b   os.statNolog+0x5b           /usr/local/Cellar/go/1.11/libexec/src/os/stat_unix.go:31
#   0x109c40c   os.Stat+0x4c                /usr/local/Cellar/go/1.11/libexec/src/os/stat.go:13
#   0x10e9488   os/exec.findExecutable+0x38     /usr/local/Cellar/go/1.11/libexec/src/os/exec/lp_unix.go:20
#   0x10e9683   os/exec.LookPath+0x173          /usr/local/Cellar/go/1.11/libexec/src/os/exec/lp_unix.go:53
#   0x10e5a66   os/exec.Command+0x1b6           /usr/local/Cellar/go/1.11/libexec/src/os/exec/exec.go:161
#   0x13095a4   main.banIps+0x84            /Users/kiyon/Code/github/go/src/github.com/kiyonlin/hello-application/testcmd/main.go:50

0: 0 [2: 192] @ 0x13095ee 0x105d0d1
#   0x13095ed   io.Pipe+0xcd        /usr/local/Cellar/go/1.11/libexec/src/io/pipe.go:189
#   0x13095ed   main.banIps+0xcd    /Users/kiyon/Code/github/go/src/github.com/kiyonlin/hello-application/testcmd/main.go:51
......

我可以看到pprof中的heap个人资料随时间增长。

这意味着在调用exec.Commandio.Pipe()函数之后,我还没有释放一些内存。

我不知道我的代码有什么问题。

谢谢大家!

0 个答案:

没有答案