Go binary portability to unsupported OS version

1,320 views
Skip to first unread message

T.J. Yang

unread,
May 22, 2013, 8:58:08 AM5/22/13
to golan...@googlegroups.com
Hi All

In R1, it list out OS and its' version requirements to compile Go compiler itself. 

As a system admin who need to support all kind of OS with various OS versions, 
My question is about the Go binary(generated static executable program by Go compiler).

A quick test(See R2) to compile helloword.go into Go binary on CentOS EL6 64-bit, and move it RedHat EL5 64 bit works fine.
My understanding is that Go binary has a built in runtime that has libc from CentOS6/RHEL6  and no worry about libc version mis-match issue.

Can I extend this ok result  to RHEL 3  64-bit OS without testing ?
or Go binary compiled on Windows 7 64 bit and expect it work in Window 2008 64-bit ?

What would be the  common denominators I need to watch out to ensure Go binary works in same OS but across OS version ?
Can Go binary from CentOS 6  work on the other OS(FreeBSD 9) as long as  ELF format (R3)and CPU architecture are the same ?

R2:

[root@os104 tmp]# ls -lrt |tail -2
-rw-r--r--  1 xymon xymon    272 May 22 07:44 helloworld.go
-rwxr-xr-x  1 root  root  420616 May 22 07:44 helloworld
[root@os104 tmp]# ldd helloworld
        not a dynamic executable
[root@os104 tmp]# file helloworld
helloworld: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
[root@os104 tmp]# go version
go version go1.1 linux/amd64
[root@os104 tmp]#


T.J. Yang

Dave Cheney

unread,
May 22, 2013, 9:13:42 AM5/22/13
to T.J. Yang, golan...@googlegroups.com
Versions of RHEL before 6 are not supported, the kernel is too old. 

Compiling a Go program in Win 7 should work on win 2008 as the windows Go runtime does a lot more dynamic introspection of its environment and win 2008 server isn't that different a kernel from win 7. 

A go binary compiled against the Linux kernel interface cannot work on FreeBSD even though they share the same underlying format for their executables, they are simply incompatible. 


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

T.J. Yang

unread,
May 22, 2013, 10:27:07 AM5/22/13
to Dave Cheney, golan...@googlegroups.com

Hi Dave,

Thanks for the response to my beginner's question. 

On Wed, May 22, 2013 at 8:13 AM, Dave Cheney <da...@cheney.net> wrote:
Versions of RHEL before 6 are not supported, the kernel is too old. 


Not that I don't trust you, I went ahead to try to compile go from src and got following error.
<snipped>
ok      os      0.155s
--- FAIL: TestExtraFiles (0.07 seconds)
        exec_test.go:302: Something already leaked - closed fd 3
        exec_test.go:359: Run: exit status 1; stdout "leaked parent file. fd = 10; want 9\n", stderr ""
FAIL
FAIL    os/exec 0.754s
<snipped>


RHEL5 are widely used in many important IT systems, can RHEL5  be supported ?



--
T.J. Yang

Niklas Schnelle

unread,
May 22, 2013, 11:19:24 AM5/22/13
to golan...@googlegroups.com
As far as I know this has to do with some kernel features the runtime uses e.g. for marking pages, network polling etc. So it's only about old kernels.
The binaries produced by the Go toolchain don't use libc at all by the way, neither compiled in nor dynamically linked. So if the kernel interface is a compatible superset all should be fine. For example an ARM binary compiled on a RaspberryPi should work on pretty much all modern Android phones even though they don't have glibc
their kernels are a bit different too but as long as the ABI is a superset that's not a problem. Note however that this static Go binary will have a hard time interfacing with the Android world. That said that same binary should also run on SailfishOS, WebOS and everything else that uses an ABI compatible Linux kernel, so no Blackberry 10 (thats QNX)

minux

unread,
May 22, 2013, 11:52:50 AM5/22/13
to T.J. Yang, Dave Cheney, golan...@googlegroups.com
On Wed, May 22, 2013 at 10:27 PM, T.J. Yang <tjyan...@gmail.com> wrote:
On Wed, May 22, 2013 at 8:13 AM, Dave Cheney <da...@cheney.net> wrote:
Versions of RHEL before 6 are not supported, the kernel is too old. 

Not that I don't trust you, I went ahead to try to compile go from src and got following error.
<snipped>
ok      os      0.155s
--- FAIL: TestExtraFiles (0.07 seconds)
        exec_test.go:302: Something already leaked - closed fd 3
        exec_test.go:359: Run: exit status 1; stdout "leaked parent file. fd = 10; want 9\n", stderr ""
expected test failure. 2.6.18 doesn't support F_CLOEXEC. 
FAIL
FAIL    os/exec 0.754s
<snipped>

RHEL5 are widely used in many important IT systems, can RHEL5  be supported ?
No, it is decided that RHEL 5's kernel is too old to support.

Henry Heikkinen

unread,
May 22, 2013, 11:54:10 AM5/22/13
to Niklas Schnelle, golan...@googlegroups.com
Hi Niklas,

Interesting. I always thought glibc was used. Does this mean that Go runtime could be ported to other operating systems basically just by implementing the ABI layer?

Regards,
Henry Heikkinen


2013/5/22 Niklas Schnelle <niklas....@gmail.com>
--

minux

unread,
May 22, 2013, 11:54:38 AM5/22/13
to Niklas Schnelle, golan...@googlegroups.com
On Wed, May 22, 2013 at 11:19 PM, Niklas Schnelle <niklas....@gmail.com> wrote:
As far as I know this has to do with some kernel features the runtime uses e.g. for marking pages, network polling etc. So it's only about old kernels.
The binaries produced by the Go toolchain don't use libc at all by the way, neither compiled in nor dynamically linked. So if the kernel
package net and os/user do depend on libc.
if you want to have absolute minimum dependencies on non-kernel components, you should disable cgo
by setting CGO_ENABLED=0 before make.bash
interface is a compatible superset all should be fine. For example an ARM binary compiled on a RaspberryPi should work on pretty much all modern Android phones even though they don't have glibc
see above, this statement is only true if you disable cgo. 

minux

unread,
May 22, 2013, 11:58:47 AM5/22/13
to Henry Heikkinen, Niklas Schnelle, golan...@googlegroups.com
On Wed, May 22, 2013 at 11:54 PM, Henry Heikkinen <r...@rce.fi> wrote:
Interesting. I always thought glibc was used. Does this mean that Go runtime could be ported to other operating systems basically just by implementing the ABI layer?
Go have it's own syscall package so it does most of things using syscall directly
without using libc.
if you disable cgo, go programs will only need the proper kernel API to run.
but for some compatibility with other programs, certain parts of the standard
library uses cgo to call libc (e.g. os/user and DNS lookup in package net)

this doesn't mean we have a ABI compatibility layer in Go's runtime,
porting Go to another OS needs some work to implement the basic
syscall interface used by syscall package and use assembly to implement
some necessary functions used by the runtime (open/read/write/create thread,
mmap, sigaction, etc.) 

Niklas Schnelle

unread,
May 22, 2013, 11:59:19 AM5/22/13
to golan...@googlegroups.com, Niklas Schnelle
But then glibc is statically linked in right? So it basically still works as long as the kernel ABI is compatible with the libc linked in, right? Are there any plans to make
at least the net package independent of libc?

minux

unread,
May 22, 2013, 12:05:42 PM5/22/13
to Niklas Schnelle, golan...@googlegroups.com
On Wed, May 22, 2013 at 11:59 PM, Niklas Schnelle <niklas....@gmail.com> wrote:
But then glibc is statically linked in right? So it basically still works as long as the kernel ABI is compatible with the libc linked in, right? Are
no. it's dynamically linked.
use ldd(1) on $GOROOT/bin/go (or godoc) to see for yourself.
there any plans to make
at least the net package independent of libc?
disable cgo (set CGO_ENABLED=0) and you will have a pure Go installation that won't
produce program that rely on libc (if cgo is disabled, all binaries produced will be statically
linked).

[Of course, the situation is different on windows, even if cgo is disabled, Go programs
will still need several dlls to run, but that's only because there isn't a published and
stable kernel syscall interface on windows]

Ian Lance Taylor

unread,
May 22, 2013, 12:44:18 PM5/22/13
to T.J. Yang, Dave Cheney, golan...@googlegroups.com
On Wed, May 22, 2013 at 7:27 AM, T.J. Yang <tjyan...@gmail.com> wrote:
>
> Not that I don't trust you, I went ahead to try to compile go from src and
> got following error.
> <snipped>
> ok os 0.155s
> --- FAIL: TestExtraFiles (0.07 seconds)
> exec_test.go:302: Something already leaked - closed fd 3
> exec_test.go:359: Run: exit status 1; stdout "leaked parent file. fd
> = 10; want 9\n", stderr ""
> FAIL
> FAIL os/exec 0.754s
> <snipped>

That error is only mildly important for real programs. If that is the
only failure, then you will most likely be OK. But I think there is
some more serious problem with the old kernel used on RHEL 5, but I
don't remember what it is.

Ian

Paulo Pinto

unread,
May 22, 2013, 1:10:12 PM5/22/13
to golang-nuts


On May 22, 6:05 pm, minux <minux...@gmail.com> wrote:
> On Wed, May 22, 2013 at 11:59 PM, Niklas Schnelle <niklas.schne...@gmail.com
>
>.....
> [Of course, the situation is different on windows, even if cgo is disabled,
> Go programs
> will still need several dlls to run, but that's only because there isn't a
> published and
> stable kernel syscall interface on windows]

As long as only system dlls are referenced and the import is done by
name instead
of ordinal, it should not matter which Windows version is being used.

--
Paulo

minux

unread,
May 22, 2013, 2:53:30 PM5/22/13
to Paulo Pinto, golang-nuts
On Thu, May 23, 2013 at 1:10 AM, Paulo Pinto <paulo....@gmail.com> wrote:
On May 22, 6:05 pm, minux <minux...@gmail.com> wrote:
> On Wed, May 22, 2013 at 11:59 PM, Niklas Schnelle <niklas.schne...@gmail.com
> [Of course, the situation is different on windows, even if cgo is disabled,
> Go programs
> will still need several dlls to run, but that's only because there isn't a
> published and
> stable kernel syscall interface on windows]

As long as only system dlls are referenced and the import is done by
name instead
of ordinal, it should not matter which Windows version is being used.
ideally it's the case. The Go runtime uses some API (such as CancelIOEx) that
only present in certain windows versions.
But, don't worry, as there is another code path that doesn't require those
features so that the minimum requirement for windows is still Windows 2000
SP4 (as documented on golang.org/doc/install)

Dave Cheney

unread,
May 22, 2013, 5:14:55 PM5/22/13
to Ian Lance Taylor, T.J. Yang, golan...@googlegroups.com
The bigger problem is only a few of the very latest RHEL 2.6.18 kernels have the VSDO 'fast' gettimeofday(2) syscall which we rely on heavily.

Ian Lance Taylor

unread,
May 22, 2013, 5:39:12 PM5/22/13
to Dave Cheney, T.J. Yang, golan...@googlegroups.com
On Wed, May 22, 2013 at 2:14 PM, Dave Cheney <da...@cheney.net> wrote:
> The bigger problem is only a few of the very latest RHEL 2.6.18 kernels have the VSDO 'fast' gettimeofday(2) syscall which we rely on heavily.

But we'll fall back to the fixed address gettimeofday which shouldn't
be too awful.

Ian

Dave Cheney

unread,
May 22, 2013, 5:42:49 PM5/22/13
to Ian Lance Taylor, T.J. Yang, golan...@googlegroups.com
More often than not calling the fast syscall in the VSDO causes a segfault unless you are using a super recent spin of RHEL5's 2.6.18~238

Ian Lance Taylor

unread,
May 22, 2013, 5:44:35 PM5/22/13
to Dave Cheney, T.J. Yang, golan...@googlegroups.com
On Wed, May 22, 2013 at 2:42 PM, Dave Cheney <da...@cheney.net> wrote:
> More often than not calling the fast syscall in the VSDO causes a segfault unless you are using a super recent spin of RHEL5's 2.6.18~238

Well, OK, that is just ridiculously lame.

Ian

todd.r...@gmail.com

unread,
Feb 5, 2014, 3:50:09 PM2/5/14
to golan...@googlegroups.com
We found that the accept4 call causes problems on old 2.6 kernels as well (QNAP NAS). We ended up hacking in a fix by editing src/pkg/net/sock_cloexec.go to include fault handling. For some reason arm and amd64 kernels are returning different errors so EACCES and EFAULT are both required. QNAP builds also needs to include their own SSL crt file, but after setting that in our code, we have a server reliably accepting connections and using SSL to our cloud

if err == nil || (err != syscall.EACCES && err != syscall.EFAULT && err != syscall.ENOSYS && err != syscall.EINVAL) {

Ian Lance Taylor

unread,
Feb 5, 2014, 6:31:28 PM2/5/14
to todd.r...@gmail.com, golang-nuts
On Wed, Feb 5, 2014 at 12:50 PM, <todd.r...@gmail.com> wrote:
> We found that the accept4 call causes problems on old 2.6 kernels as well
> (QNAP NAS). We ended up hacking in a fix by editing
> src/pkg/net/sock_cloexec.go to include fault handling. For some reason arm
> and amd64 kernels are returning different errors so EACCES and EFAULT are
> both required. QNAP builds also needs to include their own SSL crt file, but
> after setting that in our code, we have a server reliably accepting
> connections and using SSL to our cloud
>
> if err == nil || (err != syscall.EACCES && err != syscall.EFAULT && err !=
> syscall.ENOSYS && err != syscall.EINVAL) {


Can you send a change as described at http://golang.org/doc/contribute ?

Thanks.

Ian

Todd Richmond

unread,
Feb 5, 2014, 6:44:05 PM2/5/14
to Ian Lance Taylor, golang-nuts
Done - issue 7271 - thanks
Todd
Reply all
Reply to author
Forward
0 new messages