While debugging why several libgo tests on Solaris 2/SPARC were hanging in select (cf. PR go/48242, go/48243), I found that fd_set is
typedef struct fd_set { long fds_bits[__howmany(FD_SETSIZE, FD_NFDBITS)]; } fd_set; The current implementation of the FD* funcs in sysfile_posix.go assumes 64-bit fds_bits. While this doesn't make a difference on little-endian hosts, on big-endian SPARC the wrong bits are set, leading to the observed hang since there is no activity on those random fds. The following patch fixes this by moving the FD* implementation to two new sysfile_fdset{32, 64}.go files to fix this. There's almost certainly a cleaner/shorter implemenation, but this worked for me. While the affected tests don't hang anymore now, they still don't finish successfully, among others due to PR go/48222. Rainer 2011-03-24 Rainer Orth <r...@cebitec.uni-bielefeld.de> * syscalls/sysfile_posix.go (FdSet_t, FDSet, FDClr, FDIsSet) (FDZero): Move ... * syscalls/sysfile_fdset64.go: ... here. New file. * syscalls/sysfile_fdset32.go: New file. * Makefile.am (syscall_fdset_file): Use them. (go_syscall_files): Add $(syscall_fdset_file). * Makefile.in: Regenerate. diff -r e65d996c30c7 libgo/Makefile.am --- a/libgo/Makefile.am Thu Mar 24 17:24:32 2011 +0100 +++ b/libgo/Makefile.am Thu Mar 24 20:25:57 2011 +0100 @@ -1214,6 +1214,20 @@ endif # !LIBGO_IS_SOLARIS endif # !LIBGO_IS_LINUX +# Define for struct fd_set. +if LIBGO_IS_SOLARIS +if LIBGO_IS_386 +syscall_fdset_file = syscalls/sysfile_fdset32.go +else # !LIBGO_IS_386 +if LIBGO_IS_SPARC +syscall_fdset_file = syscalls/sysfile_fdset32.go +else # !LIBGO_IS_386 && !LIBGO_IS_SPARC +syscall_fdset_file = syscalls/sysfile_fdset64.go +endif # !LIBGO_IS_386 && !LIBGO_IS_SPARC +endif # !LIBGO_IS_386 && !LIBGO_IS_SPARC +else # !LIBGO_IS_SOLARIS +syscall_fdset_file = syscalls/sysfile_fdset64.go +endif # !LIBGO_IS_SOLARIS # Define ForkExec, PtraceForkExec, Exec, and Waitpid. if LIBGO_IS_RTEMS @@ -1307,6 +1321,7 @@ syscalls/syscall_$(GOOS).go \ $(GO_SYSCALLS_SYSCALL_OS_ARCH_FILE) \ syscalls/sysfile_posix.go \ + $(syscall_fdset_file) \ sysinfo.go \ syscall_arch.go go_syscall_c_files = \ diff -r e65d996c30c7 libgo/syscalls/sysfile_fdset32.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgo/syscalls/sysfile_fdset32.go Thu Mar 24 20:25:57 2011 +0100 @@ -0,0 +1,35 @@ +// sysfile_fdset.go -- POSIX fd_set handling for 32-bit fds_bits. + +// Copyright 2010, 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Support for struct fd_set. + +package syscall + +type FdSet_t struct { + Fds_bits [(FD_SETSIZE + 31) / 32]int32; +} + +func FDSet(fd int, set *FdSet_t) { + set.Fds_bits[fd / 32] |= (1 << (uint)(fd % 32)) +} + +func FDClr(fd int, set *FdSet_t) { + set.Fds_bits[fd / 32] &= ^(1 << (uint)(fd % 32)) +} + +func FDIsSet(fd int, set *FdSet_t) bool { + if set.Fds_bits[fd / 32] & (1 << (uint)(fd % 32)) != 0 { + return true + } else { + return false + } +} + +func FDZero(set *FdSet_t) { + for i := 0; i < ((FD_SETSIZE + 63) / 32); i++ { + set.Fds_bits[i] = 0 + } +} diff -r e65d996c30c7 libgo/syscalls/sysfile_fdset64.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgo/syscalls/sysfile_fdset64.go Thu Mar 24 20:25:57 2011 +0100 @@ -0,0 +1,35 @@ +// sysfile_fdset.go -- POSIX fd_set handling for 64-bit fds_bits. + +// Copyright 2010, 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Support for struct fd_set. + +package syscall + +type FdSet_t struct { + Fds_bits [(FD_SETSIZE + 63) / 64]int64; +} + +func FDSet(fd int, set *FdSet_t) { + set.Fds_bits[fd / 64] |= (1 << (uint)(fd % 64)) +} + +func FDClr(fd int, set *FdSet_t) { + set.Fds_bits[fd / 64] &= ^(1 << (uint)(fd % 64)) +} + +func FDIsSet(fd int, set *FdSet_t) bool { + if set.Fds_bits[fd / 64] & (1 << (uint)(fd % 64)) != 0 { + return true + } else { + return false + } +} + +func FDZero(set *FdSet_t) { + for i := 0; i < ((FD_SETSIZE + 63) / 64); i++ { + set.Fds_bits[i] = 0 + } +} diff -r e65d996c30c7 libgo/syscalls/sysfile_posix.go --- a/libgo/syscalls/sysfile_posix.go Thu Mar 24 17:24:32 2011 +0100 +++ b/libgo/syscalls/sysfile_posix.go Thu Mar 24 20:25:57 2011 +0100 @@ -181,32 +181,6 @@ return; } -type FdSet_t struct { - Fds_bits [(FD_SETSIZE + 63) / 64]int64; -} - -func FDSet(fd int, set *FdSet_t) { - set.Fds_bits[fd / 64] |= (1 << (uint)(fd % 64)) -} - -func FDClr(fd int, set *FdSet_t) { - set.Fds_bits[fd / 64] &= ^(1 << (uint)(fd % 64)) -} - -func FDIsSet(fd int, set *FdSet_t) bool { - if set.Fds_bits[fd / 64] & (1 << (uint)(fd % 64)) != 0 { - return true - } else { - return false - } -} - -func FDZero(set *FdSet_t) { - for i := 0; i < ((FD_SETSIZE + 63) / 64); i++ { - set.Fds_bits[i] = 0 - } -} - func Select(nfds int, r *FdSet_t, w *FdSet_t, e *FdSet_t, timeout *Timeval) (n int, errno int) { n = libc_select(nfds, (*byte)(unsafe.Pointer(r)), (*byte)(unsafe.Pointer(e)), -- ----------------------------------------------------------------------------- Rainer Orth, Center for Biotechnology, Bielefeld University