From b9ab369234ad61054cae81bb7c0fd7efbe9a3858 Mon Sep 17 00:00:00 2001 From: Ben Moss Date: Fri, 31 May 2019 14:35:23 -0400 Subject: [PATCH] Fix memory leak from not closing hcs container handles --- .../stats/cri_stats_provider_windows.go | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/pkg/kubelet/stats/cri_stats_provider_windows.go b/pkg/kubelet/stats/cri_stats_provider_windows.go index cc9934e782..d1892e9299 100644 --- a/pkg/kubelet/stats/cri_stats_provider_windows.go +++ b/pkg/kubelet/stats/cri_stats_provider_windows.go @@ -19,6 +19,7 @@ limitations under the License. package stats import ( + "fmt" "time" "github.com/Microsoft/hcsshim" @@ -40,18 +41,11 @@ func (p *criStatsProvider) listContainerNetworkStats() (map[string]*statsapi.Net stats := make(map[string]*statsapi.NetworkStats) for _, c := range containers { - container, err := hcsshim.OpenContainer(c.ID) + cstats, err := fetchContainerStats(c) if err != nil { - klog.V(4).Infof("Failed to open container %q with error '%v', continue to get stats for other containers", c.ID, err) + klog.V(4).Infof("Failed to fetch statistics for container %q with error '%v', continue to get stats for other containers", c.ID, err) continue } - - cstats, err := container.Statistics() - if err != nil { - klog.V(4).Infof("Failed to get statistics for container %q with error '%v', continue to get stats for other containers", c.ID, err) - continue - } - if len(cstats.Network) > 0 { stats[c.ID] = hcsStatsToNetworkStats(cstats.Timestamp, cstats.Network) } @@ -60,6 +54,27 @@ func (p *criStatsProvider) listContainerNetworkStats() (map[string]*statsapi.Net return stats, nil } +func fetchContainerStats(c hcsshim.ContainerProperties) (stats hcsshim.Statistics, err error) { + var ( + container hcsshim.Container + ) + container, err = hcsshim.OpenContainer(c.ID) + if err != nil { + return + } + defer func() { + if closeErr := container.Close(); closeErr != nil { + if err != nil { + err = fmt.Errorf("failed to close container after error %v; close error: %v", err, closeErr) + } else { + err = closeErr + } + } + }() + + return container.Statistics() +} + // hcsStatsToNetworkStats converts hcsshim.Statistics.Network to statsapi.NetworkStats func hcsStatsToNetworkStats(timestamp time.Time, hcsStats []hcsshim.NetworkStats) *statsapi.NetworkStats { result := &statsapi.NetworkStats{