You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I got some random crash when calling SensorsTemperatures() on MacOS (24.3.0 on arm64).
The error seems to be some kind of race-condition, since it only occur when multiple threads are calling SensorsTemperatures concurrently.
On real usage, I think my true issue is with concurrent call between SensorsTemperatures and another usage of ioKit and/or corefoundation. But I was not able to have reproducible code sample that only code one call per system (sensors, disk, cpu, mem...)
To Reproduce
package main
import (
"log/slog""sync""github.com/shirou/gopsutil/v4/sensors"
)
funcmain() {
varwg sync.WaitGroupforrange30 { // The higher is this number, the more likely issue will occur. Empirically 30 seems a good valuewg.Add(1)
gofunc() {
deferwg.Done()
r, err:=sensors.SensorsTemperatures()
iffalse {
// The log itself isn't required to produce the bug, but without// assigning SensorsTemperatures result to variable the bug don't seems to// occure, maybe due to compiler optimization ?slog.Info("sensors", slog.Any("r", r), slog.Any("err", err))
}
}()
}
wg.Wait()
}
Run the program (possibly multiple time, the race condition seems rather unlikely):
go build sensors_bug.go
while ./sensors_bug ; do echo "Sucess"; done 2>&1 | tee large_error_message.log
Environment (please complete the following information):
Mac OS: [paste the result of sw_vers and uname -a
$ sw_vers
ProductName: macOS
ProductVersion: 15.3.2
BuildVersion: 24D81
$ uname -a
Darwin mbp-de-pierre.bleemeo.work 24.3.0 Darwin Kernel Version 24.3.0: Thu Jan 2 20:24:16 PST 2025; root:xnu-11215.81.4~3/RELEASE_ARM64_T6000 arm64 arm Darwin
I think the bug is due to ioKit and/or corefoundation library being closed by another gorouting while still being used by the one who crash.
To experiment with this, I've modified TemperaturesWithContext (go mod vendor then edit "vendor/github.com/shirou/gopsutil/v4/sensors/sensors_darwin_arm64.go).
The idea is to make TemperaturesWithContext doing concurrent call (like the minimal step to reproduce it), but this time the ioKit and coreFoundation library are shared between gorouting.
func TemperaturesWithContext(_ context.Context) ([]TemperatureStat, error) {
var wg sync.WaitGroup
var (
globalResult []TemperatureStat
globalErr error
l sync.Mutex
)
ioKit, err := common.NewLibrary(common.IOKit)
if err != nil {
return nil, err
}
defer ioKit.Close()
coreFoundation, err := common.NewLibrary(common.CoreFoundation)
if err != nil {
return nil, err
}
defer coreFoundation.Close()
for range 30 { // Once more, the higher the most likely to produce the bug
wg.Add(1)
go func() {
defer wg.Done()
r, err := temperaturesWithContext(ioKit, coreFoundation)
l.Lock()
defer l.Unlock()
globalResult = r
globalErr = err
}()
}
wg.Wait()
return globalResult, globalErr
}
func temperaturesWithContext(ioKit *common.Library, coreFoundation *common.Library) ([]TemperatureStat, error) {
ta := &temperatureArm{
ioKit: ioKit,
cf: coreFoundation,
[... the remaining of the original TemperaturesWithContext unmodified]
With this change, calling TemperaturesWithContext no longer crash:
$ cat single_call.go
package main
import (
"log/slog"
"github.com/shirou/gopsutil/v4/sensors"
)
func main() {
r, err := sensors.SensorsTemperatures()
slog.Info("sensors", slog.Any("r", r), slog.Any("err", err))
}
$ go build single_call.go; while ./single_call ; do echo "Sucess"; done 2>&1 | tee large_error_message.log
If you move ioKit & coreFoundation inside the go func() { } (i.e. initialize and close) the libraries per gorouting, it will crash.
Very final note: only Sensors seems affected by this bug (maybe because sensor does the more complex usage of the ioKit/CF libraries ?): the following code don't exhibit the crash even if it use ioKit/CF concurrently on cpu/disk/mem: https://gist.github.com/PierreF/dd5864811ef6de22bfcb431810fe4f4f
The text was updated successfully, but these errors were encountered:
The reproduce condition seems to be a bit extreme, I ran the code you provided 102 times (as suggested by the length of large_error_message.log) before it crashed. In that case it means an unreasonable amount of IOKit / Core Foundation calls, and sure the sensor package is more complex, so it might be easier for it to reach system limits.
In my test, I usually get it in less than 10 tries :/
It probably means that the race condition isn't linked only to calling sensors concurrently, and might even depends on something running elsewhere... (another process on the system ? I also think to other gorouting / GC ?).
If I can found some time, I'll try to come with more realistic way to reproduce it. In real usage I don't call sensors concurrently (only concurrently with disk/cpu/mem) and I do hit the bug "fast" (like in few hundreds call to sensors - i.e. 1 hours with one call to sensors every 10 seconds).
Describe the bug
I got some random crash when calling SensorsTemperatures() on MacOS (24.3.0 on arm64).
The error seems to be some kind of race-condition, since it only occur when multiple threads are calling SensorsTemperatures concurrently.
On real usage, I think my true issue is with concurrent call between SensorsTemperatures and another usage of ioKit and/or corefoundation. But I was not able to have reproducible code sample that only code one call per system (sensors, disk, cpu, mem...)
To Reproduce
Run the program (possibly multiple time, the race condition seems rather unlikely):
It result in error like:
Expected behavior
No crash :)
Environment (please complete the following information):
sw_vers
anduname -a
gopsutil version:
Additional context
I think the bug is due to ioKit and/or corefoundation library being closed by another gorouting while still being used by the one who crash.
To experiment with this, I've modified TemperaturesWithContext (
go mod vendor
then edit"vendor/github.com/shirou/gopsutil/v4/sensors/sensors_darwin_arm64.go
).The idea is to make TemperaturesWithContext doing concurrent call (like the minimal step to reproduce it), but this time the ioKit and coreFoundation library are shared between gorouting.
With this change, calling TemperaturesWithContext no longer crash:
If you move ioKit & coreFoundation inside the
go func() { }
(i.e. initialize and close) the libraries per gorouting, it will crash.Very final note: only Sensors seems affected by this bug (maybe because sensor does the more complex usage of the ioKit/CF libraries ?): the following code don't exhibit the crash even if it use ioKit/CF concurrently on cpu/disk/mem: https://gist.github.com/PierreF/dd5864811ef6de22bfcb431810fe4f4f
The text was updated successfully, but these errors were encountered: