This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
//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
|
||||
}
|
||||
Reference in New Issue
Block a user