Skip to content

Commit 25d0004

Browse files
mauri870gopherbot
authored andcommitted
unix: fix last argument of pselect6 on linux
On Linux, the last argument of pselect6 system call is **not** a sigseg_t * pointer, but instead it is a structure of the form: struct { const sigset_t *ss; /* Pointer to signal set */ size_t ss_len; /* Size (in bytes) of object pointed }; See man 2 pselect6. Fixes #61251 Change-Id: Id0aa122a77796713bc6d624dc395d396fbc0c5e2 GitHub-Last-Rev: cb3c6d7 GitHub-Pull-Request: #167 Reviewed-on: https://go-review.googlesource.com/c/sys/+/510195 Reviewed-by: Bryan Mills <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]>
1 parent 706fa98 commit 25d0004

10 files changed

+67
-7
lines changed

unix/linux/types.go

+4
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,10 @@ const (
968968
)
969969

970970
type Sigset_t C.sigset_t
971+
type sigset_argpack struct {
972+
ss *Sigset_t
973+
ssLen uintptr // Size (in bytes) of object pointed to by ss.
974+
}
971975

972976
const _C__NSIG = C._NSIG
973977

unix/syscall_linux.go

+34-1
Original file line numberDiff line numberDiff line change
@@ -1885,7 +1885,7 @@ func Getpgrp() (pid int) {
18851885
//sys PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error)
18861886
//sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT
18871887
//sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error)
1888-
//sys Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) = SYS_PSELECT6
1888+
//sys pselect6(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *sigset_argpack) (n int, err error)
18891889
//sys read(fd int, p []byte) (n int, err error)
18901890
//sys Removexattr(path string, attr string) (err error)
18911891
//sys Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error)
@@ -2438,6 +2438,39 @@ func Getresgid() (rgid, egid, sgid int) {
24382438
return int(r), int(e), int(s)
24392439
}
24402440

2441+
// Pselect is a wrapper around the Linux pselect6 system call.
2442+
// This version does not modify the timeout argument.
2443+
func Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
2444+
// Per https://man7.org/linux/man-pages/man2/select.2.html#NOTES,
2445+
// The Linux pselect6() system call modifies its timeout argument.
2446+
// [Not modifying the argument] is the behavior required by POSIX.1-2001.
2447+
var mutableTimeout *Timespec
2448+
if timeout != nil {
2449+
mutableTimeout = new(Timespec)
2450+
*mutableTimeout = *timeout
2451+
}
2452+
2453+
// The final argument of the pselect6() system call is not a
2454+
// sigset_t * pointer, but is instead a structure
2455+
var kernelMask *sigset_argpack
2456+
if sigmask != nil {
2457+
wordBits := 32 << (^uintptr(0) >> 63) // see math.intSize
2458+
2459+
// A sigset stores one bit per signal,
2460+
// offset by 1 (because signal 0 does not exist).
2461+
// So the number of words needed is ⌈__C_NSIG - 1 / wordBits⌉.
2462+
sigsetWords := (_C__NSIG - 1 + wordBits - 1) / (wordBits)
2463+
2464+
sigsetBytes := uintptr(sigsetWords * (wordBits / 8))
2465+
kernelMask = &sigset_argpack{
2466+
ss: sigmask,
2467+
ssLen: sigsetBytes,
2468+
}
2469+
}
2470+
2471+
return pselect6(nfd, r, w, e, mutableTimeout, kernelMask)
2472+
}
2473+
24412474
/*
24422475
* Unimplemented
24432476
*/

unix/syscall_linux_amd64.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
4040
if timeout != nil {
4141
ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000}
4242
}
43-
return Pselect(nfd, r, w, e, ts, nil)
43+
return pselect6(nfd, r, w, e, ts, nil)
4444
}
4545

4646
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)

unix/syscall_linux_arm64.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
3333
if timeout != nil {
3434
ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000}
3535
}
36-
return Pselect(nfd, r, w, e, ts, nil)
36+
return pselect6(nfd, r, w, e, ts, nil)
3737
}
3838

3939
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)

unix/syscall_linux_loong64.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
2828
if timeout != nil {
2929
ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000}
3030
}
31-
return Pselect(nfd, r, w, e, ts, nil)
31+
return pselect6(nfd, r, w, e, ts, nil)
3232
}
3333

3434
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)

unix/syscall_linux_mips64x.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
3131
if timeout != nil {
3232
ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000}
3333
}
34-
return Pselect(nfd, r, w, e, ts, nil)
34+
return pselect6(nfd, r, w, e, ts, nil)
3535
}
3636

3737
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)

unix/syscall_linux_riscv64.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
3232
if timeout != nil {
3333
ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000}
3434
}
35-
return Pselect(nfd, r, w, e, ts, nil)
35+
return pselect6(nfd, r, w, e, ts, nil)
3636
}
3737

3838
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)

unix/syscall_linux_test.go

+18
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,24 @@ func TestPselect(t *testing.T) {
444444
}
445445
}
446446

447+
func TestPselectWithSigmask(t *testing.T) {
448+
var sigmask unix.Sigset_t
449+
sigmask.Val[0] |= 1 << (uint(unix.SIGUSR1) - 1)
450+
for {
451+
n, err := unix.Pselect(0, nil, nil, nil, &unix.Timespec{Sec: 0, Nsec: 0}, &sigmask)
452+
if err == unix.EINTR {
453+
t.Logf("Pselect interrupted")
454+
continue
455+
} else if err != nil {
456+
t.Fatalf("Pselect: %v", err)
457+
}
458+
if n != 0 {
459+
t.Fatalf("Pselect: got %v ready file descriptors, expected 0", n)
460+
}
461+
break
462+
}
463+
}
464+
447465
func TestSchedSetaffinity(t *testing.T) {
448466
var newMask unix.CPUSet
449467
newMask.Zero()

unix/zsyscall_linux.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

unix/ztypes_linux.go

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)