diff --git a/src/runtime/export_linux_test.go b/src/runtime/export_linux_test.go index 52afd28666e9af..f8c4b4fdc37ea2 100644 --- a/src/runtime/export_linux_test.go +++ b/src/runtime/export_linux_test.go @@ -11,6 +11,7 @@ const SigeventMaxSize = _sigev_max_size var NewOSProc0 = newosproc0 var Mincore = mincore +var ParseRelease = parseRelease type Siginfo siginfo type Sigevent sigevent diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index 493567b5303673..400dd18e7d98ad 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -962,9 +962,11 @@ func getKernelVersion() kernelVersion { // semver syntax, but allows the minor and patch versions to be // elided. func parseRelease(rel string) (major, minor, patch int, ok bool) { - // Strip anything after a dash or plus. + // Strip anything after a dash, plus, or underscore. Some + // embedded Linux vendors (e.g., Synology) append a platform + // identifier with an underscore, like "3.4.35_hi3535". for i := 0; i < len(rel); i++ { - if rel[i] == '-' || rel[i] == '+' { + if rel[i] == '-' || rel[i] == '+' || rel[i] == '_' { rel = rel[:i] break } diff --git a/src/runtime/runtime_linux_test.go b/src/runtime/runtime_linux_test.go index ab2452c9e72910..8bd3a40c99a69e 100644 --- a/src/runtime/runtime_linux_test.go +++ b/src/runtime/runtime_linux_test.go @@ -53,6 +53,31 @@ func TestMincoreErrorSign(t *testing.T) { } } +func TestParseRelease(t *testing.T) { + tests := []struct { + in string + major, minor, patch int + ok bool + }{ + {"6.1.0", 6, 1, 0, true}, + {"5.15.0-91-generic", 5, 15, 0, true}, + {"4.19.0+", 4, 19, 0, true}, + // Synology embedded Linux appends a platform identifier + // after an underscore. + {"3.4.35_hi3535", 3, 4, 35, true}, + {"2.6.32_synology", 2, 6, 32, true}, + {"3.10", 3, 10, 0, true}, + {"bogus", 0, 0, 0, false}, + } + for _, tt := range tests { + major, minor, patch, ok := ParseRelease(tt.in) + if major != tt.major || minor != tt.minor || patch != tt.patch || ok != tt.ok { + t.Errorf("ParseRelease(%q) = (%d, %d, %d, %v); want (%d, %d, %d, %v)", + tt.in, major, minor, patch, ok, tt.major, tt.minor, tt.patch, tt.ok) + } + } +} + func TestKernelStructSize(t *testing.T) { // Check that the Go definitions of structures exchanged with the kernel are // the same size as what the kernel defines.