From a289a6a5dac1e07d990423a45cc47591a4126aa7 Mon Sep 17 00:00:00 2001 From: bawenmao Date: Sun, 17 Oct 2021 10:25:47 +0800 Subject: [PATCH 1/2] Avoid time.after memory leak when calling time.After Signed-off-by: bawenmao --- collector/filesystem_linux.go | 43 ++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/collector/filesystem_linux.go b/collector/filesystem_linux.go index af60d2e6a6..58e107bfac 100644 --- a/collector/filesystem_linux.go +++ b/collector/filesystem_linux.go @@ -50,6 +50,28 @@ func (c *filesystemCollector) GetStats() ([]filesystemStats, error) { return nil, err } stats := []filesystemStats{} + mountCheckTimer := time.NewTimer(*mountTimeout) + defer mountCheckTimer.Stop() + // stuckMountWatcher listens on the given success channel and if the channel closes + // then the watcher does nothing. If instead the timeout is reached, the + // mount point that is being watched is marked as stuck. + stuckMountWatcher := func(mountPoint string, success chan struct{}, logger log.Logger) { + select { + case <-success: + // Success + case <-mountCheckTimer.C: + // Timed out, mark mount as stuck + stuckMountsMtx.Lock() + select { + case <-success: + // Success came in just after the timeout was reached, don't label the mount as stuck + default: + level.Debug(logger).Log("msg", "Mount point timed out, it is being labeled as stuck and will not be monitored", "mountpoint", mountPoint) + stuckMounts[mountPoint] = struct{}{} + } + stuckMountsMtx.Unlock() + } + } for _, labels := range mps { if c.excludedMountPointsPattern.MatchString(labels.mountPoint) { level.Debug(c.logger).Log("msg", "Ignoring mount point", "mountpoint", labels.mountPoint) @@ -118,27 +140,6 @@ func (c *filesystemCollector) GetStats() ([]filesystemStats, error) { return stats, nil } -// stuckMountWatcher listens on the given success channel and if the channel closes -// then the watcher does nothing. If instead the timeout is reached, the -// mount point that is being watched is marked as stuck. -func stuckMountWatcher(mountPoint string, success chan struct{}, logger log.Logger) { - select { - case <-success: - // Success - case <-time.After(*mountTimeout): - // Timed out, mark mount as stuck - stuckMountsMtx.Lock() - select { - case <-success: - // Success came in just after the timeout was reached, don't label the mount as stuck - default: - level.Debug(logger).Log("msg", "Mount point timed out, it is being labeled as stuck and will not be monitored", "mountpoint", mountPoint) - stuckMounts[mountPoint] = struct{}{} - } - stuckMountsMtx.Unlock() - } -} - func mountPointDetails(logger log.Logger) ([]filesystemLabels, error) { file, err := os.Open(procFilePath("1/mounts")) if errors.Is(err, os.ErrNotExist) { From d028a85a601eb04db9b2737cdbfc023c8bb686ee Mon Sep 17 00:00:00 2001 From: bawenmao Date: Wed, 20 Oct 2021 10:28:04 +0800 Subject: [PATCH 2/2] mountCheckTimer.Reset Signed-off-by: bawenmao Use Timer instead of using time.After that can avoid memory leak. Signed-off-by: bawenmao Avoid time.after memory leak when calling time.After Signed-off-by: bawenmao Use Timer instead of using time.After that maybe cause memory leak. Signed-off-by: bawenmao --- collector/filesystem_linux.go | 45 ++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/collector/filesystem_linux.go b/collector/filesystem_linux.go index 58e107bfac..4853192cb5 100644 --- a/collector/filesystem_linux.go +++ b/collector/filesystem_linux.go @@ -50,28 +50,6 @@ func (c *filesystemCollector) GetStats() ([]filesystemStats, error) { return nil, err } stats := []filesystemStats{} - mountCheckTimer := time.NewTimer(*mountTimeout) - defer mountCheckTimer.Stop() - // stuckMountWatcher listens on the given success channel and if the channel closes - // then the watcher does nothing. If instead the timeout is reached, the - // mount point that is being watched is marked as stuck. - stuckMountWatcher := func(mountPoint string, success chan struct{}, logger log.Logger) { - select { - case <-success: - // Success - case <-mountCheckTimer.C: - // Timed out, mark mount as stuck - stuckMountsMtx.Lock() - select { - case <-success: - // Success came in just after the timeout was reached, don't label the mount as stuck - default: - level.Debug(logger).Log("msg", "Mount point timed out, it is being labeled as stuck and will not be monitored", "mountpoint", mountPoint) - stuckMounts[mountPoint] = struct{}{} - } - stuckMountsMtx.Unlock() - } - } for _, labels := range mps { if c.excludedMountPointsPattern.MatchString(labels.mountPoint) { level.Debug(c.logger).Log("msg", "Ignoring mount point", "mountpoint", labels.mountPoint) @@ -140,6 +118,29 @@ func (c *filesystemCollector) GetStats() ([]filesystemStats, error) { return stats, nil } +// stuckMountWatcher listens on the given success channel and if the channel closes +// then the watcher does nothing. If instead the timeout is reached, the +// mount point that is being watched is marked as stuck. +func stuckMountWatcher(mountPoint string, success chan struct{}, logger log.Logger) { + mountCheckTimer := time.NewTimer(*mountTimeout) + defer mountCheckTimer.Stop() + select { + case <-success: + // Success + case <-mountCheckTimer.C: + // Timed out, mark mount as stuck + stuckMountsMtx.Lock() + select { + case <-success: + // Success came in just after the timeout was reached, don't label the mount as stuck + default: + level.Debug(logger).Log("msg", "Mount point timed out, it is being labeled as stuck and will not be monitored", "mountpoint", mountPoint) + stuckMounts[mountPoint] = struct{}{} + } + stuckMountsMtx.Unlock() + } +} + func mountPointDetails(logger log.Logger) ([]filesystemLabels, error) { file, err := os.Open(procFilePath("1/mounts")) if errors.Is(err, os.ErrNotExist) {