golang/go

all: require Linux kernel version 2.6.32

OneOfOne opened this issue ยท 46 comments

The last version of 2.6.23(.17) was released on February 2008 src.
The current CentOS LTS (v7) uses kernel 3.10 src.
Debian's minimum is 3.16 src.

A quick search shows lot of random issues that could have been avoided by supported a slightly newer kernel.

This is a request to bump the minimum required kernel version to at least 3.10.

mvdan commented

I support this change. Other GOOS variants fairly regularly drop support for older versions, and Linux 2.x hasn't had any upstream support at all since 2016 (2.6.32 got extended by Ubuntu/RHEL, other 2.x versions went EOL by 2012). Supporting dozens of Linux versions at once adds cost to maintenance and code complexity, makes testing more difficult, etc.

Worth noting that Debian Stretch, now "oldstable", has long-term support until mid-2022, and is on Linux 3.16 like you say. The actual stable release is on Linux 4.19, which is supported by upstream until 2024.

Similarly, CentOS v7 using Linux 3.10 is supported until 2024. So it seems like we could consider another bump sometime after.

glibc now also requires at least 3.2 version since 2.27 (announcement) for all architectures, including x86 ones.
The only issue I can imagine at the moment is old kernels used in OpenVZ VPSes, but they're starting becoming a problem for newer debian versions already.
One I have is currently running "2.6.32-042stab134.7" and debian stretch works on it (uses glibc 2.24), however updating to jessie is not possible due to its use of glibc 2.28.
For non-x86 architectures this shouldn't be an issue, which was also possibly the reason (or at least was part of) why glibc delayed their requirement for 3.2 kernel only for x86 architectures (they required 3.2 kernel in 2.25 version on other architectures).

@ianlancetaylor perhaps this should be a proposal?

Thanks, moved into proposal process.

rsc commented

This proposal has been added to the active column of the proposals project
and will now be reviewed at the weekly proposal review meetings.
โ€” rsc for the proposal review group

rsc commented

glibc requires 3.2. CentOS apparently requires 3.10.
What are we thinking of changing the minimum to?

And what are the benefits of bumping the minimum?
The link in the top comment is a search for [kernel 2.6.23] in the issue tracker.
Not all of them are bugs in 2.6.23 kernels.

Is there code we will be able to delete, like when we dropped XP?
Would we make Go binaries crash at startup if running on an old kernel?

rsc commented

We are still trying to understand this change, specifically
the exact details (which version? do we take the time to check kernel version and crash at startup on old kernels?)
and benefits (which code can be simplified or deleted?).

Any thoughts?

mvdan commented

I'll give my opinion on those questions, but I'm not the author of this proposal.

which version?

I think changing the minimum to 3.10 would be sensible, given the Linux distro info given above. I don't see a clear reason to go lower than that; even if glibc still supports 3.2 today, that kernel version went EOL in 2018 and isn't used by any supported Linux distro that I can find.

do we take the time to check kernel version and crash at startup on old kernels

We don't do that check right now with our current minimum, right? Is a new minimum different from the existing minimum, given that we're choosing it to be very conservative?

which code can be simplified or deleted?

To me, one of the main benefits is testing. I'd assume that we want to have a GOOS=linux builder running the oldest version of the kernel we support, to have more confidence that it actually works as advertised. That's a lot harder to do if that version is EOL, and isn't used by any maintained distro.

Even if one wanted to have GOOS=linux builders at multiple major versions of Linux (maybe popular LTS versions), bumping the minimum would hopefully mean fewer of those versions to worry about.

Asking for a summary of code that could be simplified, or issues that could be closed, seems reasonable. I'm not experienced in this area, but with five minutes of grepping I found five likely candidates:

// On Linux the accept4 system call was introduced in 2.6.28

// pipe2 was added in 2.6.27 and our minimum requirement is 2.6.23, so it

// in 2.6.22, Released, 8 July 2007) then fall back to utimes

// Try accept4 first for Android, then try accept for kernel older than 2.6.28

// On older kernels (before 2.6.24) the function can incorrectly

rsc commented

iant points out that timerfd was added in 2.6.25 and we probably want to depend on it for time.ExternalNow, so we should bump at least that far. And the examples show we could bump to at least 2.6.28 to simplify some code.

bradfitz points out that Synology 6.2 ships with 2.6.32.
CentOS 6 (out of support but clearly still used) is running 2.6.32 as well.

So maybe we should raise to 2.6.32, which will let us eliminate some very old things, keep some existing known use cases working, and seems not to add any known burden compared to newer versions.

Thoughts on raising to 2.6.32?

That would clean all of checks in the go runtime except one that requires 4.5+, sounds good!

mvdan commented

Bumping fewer versions is certainly better than bumping none :) We can always revisit for a newer Linux version in a couple of years.

andig commented

bradfitz points out that Synology 6.2 ships with 2.6.32.
CentOS 6 (out of support but clearly still used) is running 2.6.32 as well.

So maybe we should raise to 2.6.32, which will let us eliminate some very old things, keep some existing known use cases working, and seems not to add any known burden compared to newer versions.

Thoughts on raising to 2.6.32?

I'm not a linux pro, but Synology 6.2.4 on my NAS shows:

admin@NAS:~$ uname -a
Linux NAS 4.4.59+ #25556 SMP PREEMPT Thu Mar 4 18:03:46 CST 2021 x86_64 GNU/Linux synology_apollolake_218+

Suggestions above seem to target on 3.10, is 2.6.32 really a requirement?

rsc commented

We know of users of Go programs built for Synology 6.2 using 2.6.32, and we know of users of CentOS 6 using 2.6.32.

Suggestions above seem to target on 3.10, is 2.6.32 really a requirement?

The clear downside of 3.10 over 2.6.32 is dropping support for those systems, where we know of real instances where Go is running today.

What is the upside of 3.10 over 2.6.32?

rsc commented

Retitled to specify 2.6.32. Does anyone object to this change?

rsc commented

Based on the discussion above, this proposal seems like a likely accept.
โ€” rsc for the proposal review group

rsc commented

No change in consensus, so accepted. ๐ŸŽ‰
This issue now tracks the work of implementing the proposal.
โ€” rsc for the proposal review group

andig commented

#47390 (comment) which refers to kernel bugs in #24015 (comment) might make 3.10 an interesting target. It doesn't appear to be conclusive though. Anyway probably to late for this proposal.

Will #29114 add a builder for kernel 2.6.32, or for the newer 3.10?

https://golang.org/wiki/PortingPolicy requires a running builder for each supported port, so if we claim to support 2.6.32 we arguably ought to have a builder for it. Otherwise, we are likely to miss regressions that affect kernels in the [2.6.32, 3.10) range, and the lack of available gomote instances will make those regressions much more difficult to address.

Change https://golang.org/cl/346789 mentions this issue: os, syscall: remove fallback to pipe syscall on Linux

Change https://golang.org/cl/346790 mentions this issue: syscall: drop fallback to utimes in UtimesNano on Linux

Change https://golang.org/cl/346829 mentions this issue: unix: drop fallback to utimes in UtimesNano on Linux

Change https://golang.org/cl/346849 mentions this issue: syscall: drop fallback to accept in Accept on Linux

Change https://golang.org/cl/347329 mentions this issue: unix: drop fallback to accept in Accept on Linux

Change https://golang.org/cl/347330 mentions this issue: unix: drop fallback to inotifyInit in InotifyInit on linux/amd64

Change https://golang.org/cl/347331 mentions this issue: unix: drop fallback to pipe in Pipe on linux/arm

Change https://golang.org/cl/347349 mentions this issue: syscall: drop fallback to pipe in Pipe on linux/arm

Change https://golang.org/cl/347350 mentions this issue: syscall: use dup3 in forkAndExecInChild1 on all Linux platforms

Change https://golang.org/cl/350530 mentions this issue: syscall: implement Pipe using pipe2 syscall on all linux platforms

Change https://golang.org/cl/350549 mentions this issue: unix: implement Pipe using pipe2 syscall on all linux platforms

Change https://golang.org/cl/350552 mentions this issue: unix: use dup3 in Dup2 on all Linux platforms

Change https://go.dev/cl/386415 mentions this issue: syscall: remove accept on Linux

Change https://go.dev/cl/386954 mentions this issue: unix: remove accept on Linux

Change https://go.dev/cl/387855 mentions this issue: doc/go1.18: document minimum Linux kernel version

Change https://go.dev/cl/389354 mentions this issue: runtime: remove fallback to pipe on platforms with pipe2

Change https://go.dev/cl/410737 mentions this issue: syscall: remove unused accept on linux/loong64

Change https://go.dev/cl/411594 mentions this issue: syscall: implement EpollCreate using EpollCreate1 on all linux platforms

rsc commented

This was done and announced in go.dev/doc/go1.18.

Change https://go.dev/cl/422374 mentions this issue: syscall: remove cloexecSocket fallback path

Change https://go.dev/cl/422375 mentions this issue: internal/poll: remove fallback path in accept

Change https://go.dev/cl/424574 mentions this issue: internal/dl: update minimum Linux kernel to 2.6.32

Change https://go.dev/cl/422979 mentions this issue: internal/poll: remove detection of buggy splice on old Linux versions

Change https://go.dev/cl/424556 mentions this issue: runtime/internal/atomic: remove double-check in kernelcas on linux/arm

Change https://go.dev/cl/501275 mentions this issue: Revert "internal/poll: remove fallback path in accept"

Change https://go.dev/cl/501276 mentions this issue: Revert "net: remove fallback path in sysSocket"

Change https://go.dev/cl/501636 mentions this issue: internal/poll: update SOCK_CLOEXEC comment

Change https://go.dev/cl/501939 mentions this issue: net: update SOCK_CLOEXEC comment