Skip to content

Commit

Permalink
Fix hang during init on Windows if WMI is unavailable (#74) (#76)
Browse files Browse the repository at this point in the history
Fix hang during init on Windows if WMI is unavailable

This issue affected Windows Vista and newer. During the `init()` phase a WMI call was made to get the system boot time. If WMI wasn't fully up the call would hang which blocked the entire application from initializing.
  • Loading branch information
andrewkroh authored and tsg committed Jun 13, 2017
1 parent 4c790f7 commit 270542e
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
26 changes: 15 additions & 11 deletions sigar_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"path/filepath"
"runtime"
"strings"
"sync"
"syscall"
"time"

Expand Down Expand Up @@ -41,22 +42,15 @@ 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() {
if !version.IsWindowsVistaOrGreater() {
// 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 {
Expand All @@ -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
}
Expand Down

0 comments on commit 270542e

Please sign in to comment.