Skip to content

Commit bfe3c2e

Browse files
authored
Merge pull request shirou#452 from leafnunes/master
prevent hang on pkg import if wmi.Query hangs
2 parents 384a551 + 65598d9 commit bfe3c2e

File tree

5 files changed

+45
-11
lines changed

5 files changed

+45
-11
lines changed

cpu/cpu_windows.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package cpu
44

55
import (
6+
"context"
67
"fmt"
78
"unsafe"
89

@@ -81,8 +82,9 @@ func Info() ([]InfoStat, error) {
8182
var ret []InfoStat
8283
var dst []Win32_Processor
8384
q := wmi.CreateQuery(&dst, "")
84-
err := wmi.Query(q, &dst)
85-
if err != nil {
85+
ctx, cancel := context.WithTimeout(context.Background(), common.Timeout)
86+
defer cancel()
87+
if err := common.WMIQueryWithContext(ctx, q, &dst); err != nil {
8688
return ret, err
8789
}
8890

@@ -113,8 +115,11 @@ func Info() ([]InfoStat, error) {
113115
// Name property is the key by which overall, per cpu and per core metric is known.
114116
func PerfInfo() ([]Win32_PerfFormattedData_Counters_ProcessorInformation, error) {
115117
var ret []Win32_PerfFormattedData_Counters_ProcessorInformation
118+
116119
q := wmi.CreateQuery(&ret, "")
117-
err := wmi.Query(q, &ret)
120+
ctx, cancel := context.WithTimeout(context.Background(), common.Timeout)
121+
defer cancel()
122+
err := common.WMIQueryWithContext(ctx, q, &ret)
118123
return ret, err
119124
}
120125

@@ -123,7 +128,9 @@ func PerfInfo() ([]Win32_PerfFormattedData_Counters_ProcessorInformation, error)
123128
func ProcInfo() ([]Win32_PerfFormattedData_PerfOS_System, error) {
124129
var ret []Win32_PerfFormattedData_PerfOS_System
125130
q := wmi.CreateQuery(&ret, "")
126-
err := wmi.Query(q, &ret)
131+
ctx, cancel := context.WithTimeout(context.Background(), common.Timeout)
132+
defer cancel()
133+
err := common.WMIQueryWithContext(ctx, q, &ret)
127134
return ret, err
128135
}
129136

disk/disk_windows.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ package disk
44

55
import (
66
"bytes"
7+
"context"
78
"unsafe"
89

9-
"github.com/StackExchange/wmi"
1010
"github.com/shirou/gopsutil/internal/common"
1111
"golang.org/x/sys/windows"
1212
)
@@ -132,7 +132,9 @@ func IOCounters(names ...string) (map[string]IOCountersStat, error) {
132132
ret := make(map[string]IOCountersStat, 0)
133133
var dst []Win32_PerfFormattedData
134134

135-
err := wmi.Query("SELECT * FROM Win32_PerfFormattedData_PerfDisk_LogicalDisk ", &dst)
135+
ctx, cancel := context.WithTimeout(context.Background(), common.Timeout)
136+
defer cancel()
137+
err := common.WMIQueryWithContext(ctx, "SELECT * FROM Win32_PerfFormattedData_PerfDisk_LogicalDisk", &dst)
136138
if err != nil {
137139
return ret, err
138140
}

host/host_windows.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package host
44

55
import (
6+
"context"
67
"fmt"
78
"os"
89
"runtime"
@@ -109,7 +110,9 @@ func getMachineGuid() (string, error) {
109110
func GetOSInfo() (Win32_OperatingSystem, error) {
110111
var dst []Win32_OperatingSystem
111112
q := wmi.CreateQuery(&dst, "")
112-
err := wmi.Query(q, &dst)
113+
ctx, cancel := context.WithTimeout(context.Background(), common.Timeout)
114+
defer cancel()
115+
err := common.WMIQueryWithContext(ctx, q, &dst)
113116
if err != nil {
114117
return Win32_OperatingSystem{}, err
115118
}

internal/common/common_windows.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
package common
44

55
import (
6+
"context"
67
"unsafe"
78

9+
"github.com/StackExchange/wmi"
810
"golang.org/x/sys/windows"
911
)
1012

@@ -49,7 +51,7 @@ var (
4951
ModNt = windows.NewLazyDLL("ntdll.dll")
5052
ModPdh = windows.NewLazyDLL("pdh.dll")
5153
ModPsapi = windows.NewLazyDLL("psapi.dll")
52-
54+
5355
ProcGetSystemTimes = Modkernel32.NewProc("GetSystemTimes")
5456
ProcNtQuerySystemInformation = ModNt.NewProc("NtQuerySystemInformation")
5557
PdhOpenQuery = ModPdh.NewProc("PdhOpenQuery")
@@ -110,3 +112,18 @@ func CreateCounter(query windows.Handle, pname, cname string) (*CounterInfo, err
110112
Counter: counter,
111113
}, nil
112114
}
115+
116+
// WMIQueryWithContext - wraps wmi.Query with a timed-out context to avoid hanging
117+
func WMIQueryWithContext(ctx context.Context, query string, dst interface{}, connectServerArgs ...interface{}) error {
118+
errChan := make(chan error, 1)
119+
go func() {
120+
errChan <- wmi.Query(query, dst, connectServerArgs...)
121+
}()
122+
123+
select {
124+
case <-ctx.Done():
125+
return ctx.Err()
126+
case err := <-errChan:
127+
return err
128+
}
129+
}

process/process_windows.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package process
44

55
import (
6+
"context"
67
"fmt"
78
"strings"
89
"syscall"
@@ -130,8 +131,10 @@ func GetWin32Proc(pid int32) ([]Win32_Process, error) {
130131
var dst []Win32_Process
131132
query := fmt.Sprintf("WHERE ProcessId = %d", pid)
132133
q := wmi.CreateQuery(&dst, query)
133-
134-
if err := wmi.Query(q, &dst); err != nil {
134+
ctx, cancel := context.WithTimeout(context.Background(), common.Timeout)
135+
defer cancel()
136+
err := common.WMIQueryWithContext(ctx, q, &dst)
137+
if err != nil {
135138
return []Win32_Process{}, fmt.Errorf("could not get win32Proc: %s", err)
136139
}
137140

@@ -333,7 +336,9 @@ func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
333336
func (p *Process) Children() ([]*Process, error) {
334337
var dst []Win32_Process
335338
query := wmi.CreateQuery(&dst, fmt.Sprintf("Where ParentProcessId = %d", p.Pid))
336-
err := wmi.Query(query, &dst)
339+
ctx, cancel := context.WithTimeout(context.Background(), common.Timeout)
340+
defer cancel()
341+
err := common.WMIQueryWithContext(ctx, query, &dst)
337342
if err != nil {
338343
return nil, err
339344
}

0 commit comments

Comments
 (0)