in metric/system/process/process_windows.go [105:146]
func FetchNumThreads(pid int) (int, error) {
targetProcessHandle, err := syscall.OpenProcess(
xsyswindows.PROCESS_QUERY_INFORMATION,
false,
uint32(pid))
if err != nil {
return 0, fmt.Errorf("OpenProcess failed for PID %d: %w", pid, err)
}
defer func() {
_ = syscall.CloseHandle(targetProcessHandle)
}()
currentProcessHandle, err := syscall.GetCurrentProcess()
if err != nil {
return 0, fmt.Errorf("GetCurrentProcess failed for PID %d: %w", pid, err)
}
// The pseudo handle need not be closed when it is no longer
// needed, calling CloseHandle has no effect. Adding here to
// remind us to close any handles we open.
defer func() {
_ = syscall.CloseHandle(currentProcessHandle)
}()
var snapshotHandle syscall.Handle
err = PssCaptureSnapshot(targetProcessHandle, PSSCaptureThreads, 0, &snapshotHandle)
if err != nil {
return 0, fmt.Errorf("PssCaptureSnapshot failed for PID %d: %w", pid, err)
}
info := PssThreadInformation{}
buffSize := unsafe.Sizeof(info)
queryErr := PssQuerySnapshot(snapshotHandle, PssQueryThreadInformation, &info, uint32(buffSize))
freeErr := PssFreeSnapshot(currentProcessHandle, snapshotHandle)
if queryErr != nil || freeErr != nil {
//Join discards any nil errors
return 0, errors.Join(
fmt.Errorf("PssQuerySnapshot failed: %w", queryErr),
fmt.Errorf("PssFreeSnapshot failed: %w", freeErr))
}
return int(info.ThreadsCaptured), nil
}