Skip to content

sysfs: don't hang on cpufreq files that return EAGAIN - #879

Merged
SuperQ merged 2 commits into
prometheus:masterfrom
blovett:sysfs-cpufreq-eagain
Oct 19, 2026
Merged

SuperQ merged 2 commits into
prometheus:masterfrom
blovett:sysfs-cpufreq-eagain

Conversation

@blovett

@blovett blovett commented Oct 8, 2026

Copy link
Copy Markdown

Fixes prometheus/node_exporter#3791.

On arm64, a read of cpuinfo_avg_freq can return EAGAIN. This occurs when all CPUs in the policy are idle. #829 added this file to SystemCpufreq.

os.ReadFile adds the file to the Go netpoller. After EAGAIN, it waits for a readiness event. kernfs does not send this event. Because of this, the read does not complete and SystemCpufreq does not return. For each scrape, node_exporter 1.12 does not release one goroutine and one file descriptor.

SysReadFile prevents this problem. parseCpufreqCpuinfo uses it for the string attributes. This change also uses SysReadUintFromFile for the uint attributes. If the read returns EAGAIN, the function does not use the value. This is the same as for a missing file.

Testing

make test and golangci-lint pass. The test fixtures cannot return EAGAIN. For this reason, this change does not add a unit test. If you want a unit test, I can add one.

I built node_exporter 1.12.1 with procfs master, and with procfs master and this change. I scraped each binary 20 times on a Radxa Orion O6 (arm64, cppc_cpufreq):

Successful scrapes Goroutines File descriptors
master 8/20 4 → 86 7 → 53
this change 20/20 4 → 4 7 → 7

The end-to-end test output is the same for the two binaries.

#861 is a different solution. It sets a 5 s deadline for each read. This also stops the leak. But on an idle system, most calls took 5 s.

@SuperQ

Generated with assistance by Claude Code.

@daveoy

daveoy commented Oct 15, 2026

Copy link
Copy Markdown

started a thread on CNCF slack about incorporating this change https://cloud-native.slack.com/archives/C01AUBA4PFE/p1792097716085379 -- or we can continue here

but i would like to +1 this as we're hitting it in our org accross nvidia GBx00 systems on 6.x kernels in node_exporter

Comment thread sysfs/system_cpu.go Outdated

@bwplotka bwplotka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM mod Ben's comment

Comment thread sysfs/system_cpu.go Outdated
On arm64, reading cpuinfo_avg_freq returns EAGAIN when the CPU has not
ticked recently and every other CPU in the policy is idle
(arch_freq_get_on_cpu: "No alternative to pull info from").

os.ReadFile registers sysfs fds with the netpoller, and on EAGAIN waits
for a readiness edge that kernfs never sends, so the read never returns.
SystemCpufreq waits on every per-CPU read, so the whole call hangs, and
node_exporter's cpufreq collector leaks a goroutine and an fd on every
scrape.

Read the uint attributes with SysReadUintFromFile, which already exists
for this failure mode and is already used for the string attributes, and
skip the value on EAGAIN like a missing or unreadable file.

Fixes prometheus/node_exporter#3791

Signed-off-by: Ben Lovett <64740+blovett@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@blovett
blovett force-pushed the sysfs-cpufreq-eagain branch from d93f108 to 571d678 Compare October 16, 2026 15:14

@SuperQ SuperQ left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@SuperQ
SuperQ merged commit 43ec1ee into prometheus:master Oct 19, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cpufreq collector hangs forever on arm64 with cppc_cpufreq, leaking a goroutine and an fd per scrape

4 participants