OpenNHP/opennhp · critical

Failed to get the system running time:

Error message

Failed to get the system running time: 

What it means

The ebpf engine package's init() calls syscall.Sysinfo to read system uptime and derive the boot time (bootTime), which ebpf time-translation later depends on. If the Sysinfo syscall fails, init panics with 'Failed to get the system running time: ' + the OS error, so the whole nhp-ac process aborts at startup. Because it is a package init, this fires before main() and cannot be caught.

Solutions

  1. Check the panic text's OS error (e.g. ENOSYS, permission denied) to identify the blocked syscall.
  2. Adjust the sandbox/seccomp profile to allow sysinfo, or run on a standard Linux kernel.
  3. If portability is required, replace the panic in init() with a deferred/lazy computation of bootTime (compute on first use) and log/return an error instead of crashing.
  4. Fallback: derive boot time from /proc/stat's 'btime' field if Sysinfo is unavailable.
  5. Report/fix upstream if the target platform genuinely lacks Sysinfo support in Go's syscall package.

Example fix

// before
func init() {
	var info syscall.Sysinfo_t
	if err := syscall.Sysinfo(&info); err != nil {
		panic("Failed to get the system running time: " + err.Error())
	}
	bootTime = now.Add(-time.Duration(info.Uptime) * time.Second)
}
// after
var initBootTimeErr error

func init() {
	var info syscall.Sysinfo_t
	if err := syscall.Sysinfo(&info); err != nil {
		initBootTimeErr = fmt.Errorf("failed to get the system running time: %w", err)
		log.Error(initBootTimeErr.Error())
		return
	}
	bootTime = time.Now().Add(-time.Duration(info.Uptime) * time.Second)
}
Defensive patterns

Strategy: fallback

Validate before calling

// Pre-flight check in deployment scripts before starting nhp-ac
if ! grep -q '^btime' /proc/stat 2>/dev/null; then
  echo 'warning: sysinfo/proc may be restricted; ebpf boot-time derivation may fail'
fi

Try / catch

// init() cannot be caught; recover at the boundary that imports the package
func safeStart() (err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("ebpf engine init panicked: %v", r)
		}
	}()
	_ = ebpfegine.BootTime() // triggers package init
	return nil
}

Prevention

When it happens

Trigger: Starting any binary that imports endpoints/ac/ebpf when syscall.Sysinfo fails — e.g. the kernel does not provide the sysinfo syscall or it is blocked by the sandbox.

Common situations: Running nhp-ac in gVisor/containers or restricted sandboxes that filter syscalls; cross-compiling to an OS/arch where syscall.Sysinfo is unsupported; seccomp profiles dropping SYS_sysinfo.

Understand the failure class

Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.

Related errors


AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07). Data as JSON: /api/errors/c7538f433a6a4cfc. Report an issue: GitHub.

Appendix: source

Thrown at endpoints/ac/ebpf/ebpfegine.go:68

type Event struct {
	Timestamp  uint64 `ebpf:"timestamp"`
	Action     uint8  `ebpf:"action"`
	SrcIP      uint32 `ebpf:"src_ip"`
	DstIP      uint32 `ebpf:"dst_ip"`
	SrcPort    uint16 `ebpf:"src_port"`
	DstPort    uint16 `ebpf:"dst_port"`
	Protocol   uint8  `ebpf:"protocol"`
	PayloadLen uint16 `ebpf:"payload_len"`
}

var xdpLink link.Link
var tcLink link.Link
var bootTime time.Time

func init() {
	var info syscall.Sysinfo_t
	if err := syscall.Sysinfo(&info); err != nil {
		panic("Failed to get the system running time: " + err.Error())
	}

	now := time.Now()
	bootTime = now.Add(-time.Duration(info.Uptime) * time.Second)
	log.Info("​​System boot time: %v", bootTime)
}

func EbpfEngineLoad(dirPath string, logLevel int, acId string) error {
	CleanupBPFFiles()
	if err := rlimit.RemoveMemlock(); err != nil {
		log.Error("Failed to remove memlock limit")
	}

	const ebpfenginename string = "nhp_ebpf_xdp.o"
	const tcObjName string = "tc_egress.o"
	//ebpf nhp_ebpf_xdp.o save to etc/ after clang compile
	bpfDir := "etc"
	specPath := filepath.Join(bpfDir, ebpfenginename)

View on GitHub (pinned to 6e04ca5ff0)