Skip to content

unix: fix last argument of pselect6 on linux #167

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions unix/linux/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,10 @@ const (
)

type Sigset_t C.sigset_t
type sigset_argpack struct {
ss *Sigset_t
ssLen uintptr // Size (in bytes) of object pointed to by ss.
}

const _C__NSIG = C._NSIG

Expand Down
35 changes: 34 additions & 1 deletion unix/syscall_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -1885,7 +1885,7 @@ func Getpgrp() (pid int) {
//sys PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error)
//sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT
//sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error)
//sys Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) = SYS_PSELECT6
//sys pselect6(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *sigset_argpack) (n int, err error)
//sys read(fd int, p []byte) (n int, err error)
//sys Removexattr(path string, attr string) (err error)
//sys Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error)
Expand Down Expand Up @@ -2438,6 +2438,39 @@ func Getresgid() (rgid, egid, sgid int) {
return int(r), int(e), int(s)
}

// Pselect is a wrapper around the Linux pselect6 system call.
// This version does not modify the timeout argument.
func Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
// Per https://man7.org/linux/man-pages/man2/select.2.html#NOTES,
// The Linux pselect6() system call modifies its timeout argument.
// [Not modifying the argument] is the behavior required by POSIX.1-2001.
var mutableTimeout *Timespec
if timeout != nil {
mutableTimeout = new(Timespec)
*mutableTimeout = *timeout
}

// The final argument of the pselect6() system call is not a
// sigset_t * pointer, but is instead a structure
var kernelMask *sigset_argpack
if sigmask != nil {
wordBits := 32 << (^uintptr(0) >> 63) // see math.intSize

// A sigset stores one bit per signal,
// offset by 1 (because signal 0 does not exist).
// So the number of words needed is ⌈__C_NSIG - 1 / wordBits⌉.
sigsetWords := (_C__NSIG - 1 + wordBits - 1) / (wordBits)

sigsetBytes := uintptr(sigsetWords * (wordBits / 8))
kernelMask = &sigset_argpack{
ss: sigmask,
ssLen: sigsetBytes,
}
}

return pselect6(nfd, r, w, e, mutableTimeout, kernelMask)
}

/*
* Unimplemented
*/
Expand Down
2 changes: 1 addition & 1 deletion unix/syscall_linux_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
if timeout != nil {
ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000}
}
return Pselect(nfd, r, w, e, ts, nil)
return pselect6(nfd, r, w, e, ts, nil)
}

//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
Expand Down
2 changes: 1 addition & 1 deletion unix/syscall_linux_arm64.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
if timeout != nil {
ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000}
}
return Pselect(nfd, r, w, e, ts, nil)
return pselect6(nfd, r, w, e, ts, nil)
}

//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
Expand Down
2 changes: 1 addition & 1 deletion unix/syscall_linux_loong64.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
if timeout != nil {
ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000}
}
return Pselect(nfd, r, w, e, ts, nil)
return pselect6(nfd, r, w, e, ts, nil)
}

//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
Expand Down
2 changes: 1 addition & 1 deletion unix/syscall_linux_mips64x.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
if timeout != nil {
ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000}
}
return Pselect(nfd, r, w, e, ts, nil)
return pselect6(nfd, r, w, e, ts, nil)
}

//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
Expand Down
2 changes: 1 addition & 1 deletion unix/syscall_linux_riscv64.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
if timeout != nil {
ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000}
}
return Pselect(nfd, r, w, e, ts, nil)
return pselect6(nfd, r, w, e, ts, nil)
}

//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
Expand Down
18 changes: 18 additions & 0 deletions unix/syscall_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,24 @@ func TestPselect(t *testing.T) {
}
}

func TestPselectWithSigmask(t *testing.T) {
var sigmask unix.Sigset_t
sigmask.Val[0] |= 1 << (uint(unix.SIGUSR1) - 1)
for {
n, err := unix.Pselect(0, nil, nil, nil, &unix.Timespec{Sec: 0, Nsec: 0}, &sigmask)
if err == unix.EINTR {
t.Logf("Pselect interrupted")
continue
} else if err != nil {
t.Fatalf("Pselect: %v", err)
}
if n != 0 {
t.Fatalf("Pselect: got %v ready file descriptors, expected 0", n)
}
break
}
}

func TestSchedSetaffinity(t *testing.T) {
var newMask unix.CPUSet
newMask.Zero()
Expand Down
2 changes: 1 addition & 1 deletion unix/zsyscall_linux.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions unix/ztypes_linux.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.