elastic / elastic/go-sysinfo

[windows] go-sysinfo KernelVersion() re-stats ntoskrnl.exe on every call — cache the result

Open Beginner friendly
#293 3 comments 1 reaction 0 assignees View on GitHub
Team:Elastic-Agent-Control-Plane
Dominant language
Go
Stars
405
Forks
91
PR merge metrics
No merged PRs in 30d

Description

`KernelVersion()` on Windows has no cache. It calls `GetFileVersionInfo` against `%SystemRoot%\System32\ntoskrnl.exe` on every invocation. The kernel version cannot change while the process runs. Every repeated call is unnecessary.

**Why this matters:**

`GetFileVersionInfo` issues a syscall to stat the file. Go runs syscalls on real OS threads. If the syscall blocks, the Go runtime spawns a new OS thread to keep other goroutines running. Each blocked goroutine produces another thread. A caller that collects host info in a tight loop — or from many concurrent goroutines — can produce a large number of OS threads, all blocked on the same file stat. This amplifies any transient filesystem stall into a thread explosion.

**Code path:**

- `providers/windows/kernel_windows.go` — `KernelVersion()` calls `GetFileVersionInfo` unconditionally.
- `providers/windows/host_windows.go` — `newHost()` calls `r.kernelVersion(h)` on every host-info collection. It does not store the result.

**Fix:**

Cache the result on first call. Use \`sync.Once\`. The kernel version is constant for the life of the process.

```go
type windowsSystem struct {
kernelVersionOnce sync.Once
kernelVersionVal string
kernelVersionErr error
}

func (r *windowsSystem) KernelVersion() (string, error) {
r.kernelVersionOnce.Do(func() {
r.kernelVersionVal, r.kernelVersionErr = getKernelVersion()
})
return r.kernelVersionVal, r.kernelVersionErr
}
```

No TTL is needed. The value does not change.

**Affected versions:** Any caller that collects host info in a loop on Windows. Confirmed in Elastic Agent 9.4 with \`metricbeat.default: otel\`.

Contributor guide

Open the contributing guide

Research direction

Start with providers/windows/kernel_windows.go to trace KernelVersion() and then inspect providers/windows/host_windows.go to confirm how newHost() invokes it. Add first-call caching with sync.Once, preserving the returned version and error, and verify repeated host-info collection no longer re-stats ntoskrnl.exe.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
operating-systems
Issue type
Refactor
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.