golang 1.11 os / exec: exec.com и проблема утечки памяти - PullRequest
0 голосов
/ 29 ноября 2018

Моя ОС - 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
......

Я вижу, как профиль heap в pprof растет со временем.

Это означает, что после exec.Command и io.Pipe() функциипозвонил, у меня нет свободной памяти.

Я не знаю, в чем проблема с моим кодом.

Спасибо всем!

...