Public source validation / validate (push) Failing after 3m8s
47 lines
1.4 KiB
Go
47 lines
1.4 KiB
Go
//go:build linux
|
|
|
|
package hostcollect
|
|
|
|
import (
|
|
"math"
|
|
"syscall"
|
|
|
|
"github.com/itworx/pulse/internal/host"
|
|
)
|
|
|
|
// Bits of the adjtimex status word, defined here because the standard syscall package
|
|
// does not export them on every architecture.
|
|
const (
|
|
staUnsync = 0x0040 // clock is not synchronised to a reference
|
|
staNano = 0x2000 // offset and precision are in nanoseconds, not microseconds
|
|
timeError = 5 // adjtimex state: the clock is not synchronised
|
|
)
|
|
|
|
// readClockSync asks the kernel about clock discipline with adjtimex(2) in read mode.
|
|
//
|
|
// A zeroed Timex has Modes == 0, which makes the call a pure read: it adjusts nothing.
|
|
// Docker's default seccomp profile still gates adjtimex behind CAP_SYS_TIME, which the
|
|
// agent drops, so the expected in-container result is EPERM. The caller turns that into
|
|
// a warning; see Collector.clock.
|
|
func readClockSync() (host.RawTime, error) {
|
|
timex := syscall.Timex{}
|
|
state, err := syscall.Adjtimex(&timex)
|
|
if err != nil {
|
|
return host.RawTime{}, err
|
|
}
|
|
divisor := 1e6
|
|
if timex.Status&staNano != 0 {
|
|
divisor = 1e9
|
|
}
|
|
offset := math.Abs(float64(timex.Offset)) / divisor
|
|
if math.IsNaN(offset) || math.IsInf(offset, 0) {
|
|
offset = 0
|
|
}
|
|
return host.RawTime{
|
|
Synchronized: timex.Status&staUnsync == 0 && state != timeError,
|
|
// The kernel exposes no stratum; that belongs to the NTP daemon, which the
|
|
// agent deliberately does not talk to.
|
|
OffsetSeconds: offset,
|
|
}, nil
|
|
}
|