diff --git a/CHANGELOG.md b/CHANGELOG.md index 548b1ceee..039bf2f84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added ### Changed +- Fixed Windows issue that caused a hang during `init()` if WMI wasn't ready. #74 ### Deprecated diff --git a/sigar_windows.go b/sigar_windows.go index c5f665d92..79105aeba 100644 --- a/sigar_windows.go +++ b/sigar_windows.go @@ -7,6 +7,7 @@ import ( "path/filepath" "runtime" "strings" + "sync" "syscall" "time" @@ -41,7 +42,8 @@ var ( // bootTime is the time when the OS was last booted. This value may be nil // on operating systems that do not support the WMI query used to obtain it. - bootTime *time.Time + bootTime *time.Time + bootTimeLock sync.Mutex ) func init() { @@ -49,14 +51,6 @@ func init() { // PROCESS_QUERY_LIMITED_INFORMATION cannot be used on 2003 or XP. processQueryLimitedInfoAccess = syscall.PROCESS_QUERY_INFORMATION } - - if version.IsWindowsVistaOrGreater() { - // The minimum supported client for Win32_OperatingSystem is Windows Vista. - os, err := getWin32OperatingSystem() - if err == nil { - bootTime = &os.LastBootUpTime - } - } } func (self *LoadAverage) Get() error { @@ -80,11 +74,21 @@ func (self *ProcFDUsage) Get(pid int) error { } func (self *Uptime) Get() error { - if bootTime == nil { - // Minimum supported OS is Windows Vista. + // Minimum supported OS is Windows Vista. + if !version.IsWindowsVistaOrGreater() { return ErrNotImplemented{runtime.GOOS} } + bootTimeLock.Lock() + defer bootTimeLock.Unlock() + if bootTime == nil { + os, err := getWin32OperatingSystem() + if err != nil { + return errors.Wrap(err, "failed to get boot time using WMI") + } + bootTime = &os.LastBootUpTime + } + self.Length = time.Since(*bootTime).Seconds() return nil }