{"record":{"id":"c7538f433a6a4cfc","repo":"OpenNHP/opennhp","slug":"failed-to-get-the-system-running-time","errorCode":null,"errorMessage":"Failed to get the system running time: ","messagePattern":"Failed to get the system running time: ","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"endpoints/ac/ebpf/ebpfegine.go","lineNumber":68,"sourceCode":"type Event struct {\n\tTimestamp  uint64 `ebpf:\"timestamp\"`\n\tAction     uint8  `ebpf:\"action\"`\n\tSrcIP      uint32 `ebpf:\"src_ip\"`\n\tDstIP      uint32 `ebpf:\"dst_ip\"`\n\tSrcPort    uint16 `ebpf:\"src_port\"`\n\tDstPort    uint16 `ebpf:\"dst_port\"`\n\tProtocol   uint8  `ebpf:\"protocol\"`\n\tPayloadLen uint16 `ebpf:\"payload_len\"`\n}\n\nvar xdpLink link.Link\nvar tcLink link.Link\nvar bootTime time.Time\n\nfunc init() {\n\tvar info syscall.Sysinfo_t\n\tif err := syscall.Sysinfo(&info); err != nil {\n\t\tpanic(\"Failed to get the system running time: \" + err.Error())\n\t}\n\n\tnow := time.Now()\n\tbootTime = now.Add(-time.Duration(info.Uptime) * time.Second)\n\tlog.Info(\"​​System boot time: %v\", bootTime)\n}\n\nfunc EbpfEngineLoad(dirPath string, logLevel int, acId string) error {\n\tCleanupBPFFiles()\n\tif err := rlimit.RemoveMemlock(); err != nil {\n\t\tlog.Error(\"Failed to remove memlock limit\")\n\t}\n\n\tconst ebpfenginename string = \"nhp_ebpf_xdp.o\"\n\tconst tcObjName string = \"tc_egress.o\"\n\t//ebpf nhp_ebpf_xdp.o save to etc/ after clang compile\n\tbpfDir := \"etc\"\n\tspecPath := filepath.Join(bpfDir, ebpfenginename)","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/endpoints/ac/ebpf/ebpfegine.go#L50-L86","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the panic text's OS error (e.g. ENOSYS, permission denied) to identify the blocked syscall.","Adjust the sandbox/seccomp profile to allow sysinfo, or run on a standard Linux kernel.","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.","Fallback: derive boot time from /proc/stat's 'btime' field if Sysinfo is unavailable.","Report/fix upstream if the target platform genuinely lacks Sysinfo support in Go's syscall package."],"exampleFix":"// before\nfunc init() {\n\tvar info syscall.Sysinfo_t\n\tif err := syscall.Sysinfo(&info); err != nil {\n\t\tpanic(\"Failed to get the system running time: \" + err.Error())\n\t}\n\tbootTime = now.Add(-time.Duration(info.Uptime) * time.Second)\n}\n// after\nvar initBootTimeErr error\n\nfunc init() {\n\tvar info syscall.Sysinfo_t\n\tif err := syscall.Sysinfo(&info); err != nil {\n\t\tinitBootTimeErr = fmt.Errorf(\"failed to get the system running time: %w\", err)\n\t\tlog.Error(initBootTimeErr.Error())\n\t\treturn\n\t}\n\tbootTime = time.Now().Add(-time.Duration(info.Uptime) * time.Second)\n}","handlingStrategy":"fallback","validationCode":"// Pre-flight check in deployment scripts before starting nhp-ac\nif ! grep -q '^btime' /proc/stat 2>/dev/null; then\n  echo 'warning: sysinfo/proc may be restricted; ebpf boot-time derivation may fail'\nfi","typeGuard":null,"tryCatchPattern":"// init() cannot be caught; recover at the boundary that imports the package\nfunc safeStart() (err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\terr = fmt.Errorf(\"ebpf engine init panicked: %v\", r)\n\t\t}\n\t}()\n\t_ = ebpfegine.BootTime() // triggers package init\n\treturn nil\n}","preventionTips":["Deploy nhp-ac only on standard Linux kernels where sysinfo is available.","Review container seccomp profiles to ensure SYS_sysinfo is allowed.","Prefer builds where boot-time computation is lazy rather than done in package init().","Smoke-test the daemon in the target sandbox (gVisor, Firecracker, etc.) before production rollout."],"tags":["ebpf","linux","syscall","panic","startup"],"backgroundTag":"unsupported-platform","analyzedSha":"6e04ca5ff03222a699c24205cd4bf8fee9af7ffe","analyzedAt":"2026-09-07T15:44:59.941Z","contentChangedAt":"2026-09-07T15:44:59.941Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}