Attention is currently required from:
Gerrit Bot has uploaded this change for review.
linux: fix last argument of pselect6
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: 3c1041b1cfd17a1c60a33991521f7acd8ba0d786
GitHub-Pull-Request: golang/sys#167
---
M unix/linux/types.go
M unix/syscall_linux.go
M unix/syscall_linux_test.go
M unix/zsyscall_linux.go
M unix/ztypes_linux.go
5 files changed, 75 insertions(+), 2 deletions(-)
diff --git a/unix/linux/types.go b/unix/linux/types.go
index 469ff6b..1902573 100644
--- a/unix/linux/types.go
+++ b/unix/linux/types.go
@@ -968,6 +968,10 @@
)
type Sigset_t C.sigset_t
+type pselect6Sigset_t struct {
+ ss *Sigset_t
+ ssLen uintptr // Size (in bytes) of object pointed to by ss.
+}
const _C__NSIG = C._NSIG
diff --git a/unix/syscall_linux.go b/unix/syscall_linux.go
index 332a74b..e296688 100644
--- a/unix/syscall_linux.go
+++ b/unix/syscall_linux.go
@@ -1885,7 +1885,7 @@
//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 *pselect6Sigset_t) (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)
@@ -2438,6 +2438,36 @@
return int(r), int(e), int(s)
}
+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 *pselect6Sigset_t
+ if sigmask != nil {
+ wordBits := 32 << (^uintptr(0) >> 63)
+ sigsetWords := (_C__NSIG - 1 + wordBits - 1) / (wordBits)
+
+ // 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⌉.
+ sigsetBytes := sigsetWords * (wordBits / 8)
+ kernelMask = &pselect6Sigset_t{
+ ss: sigmask,
+ ssLen: uintptr(sigsetBytes),
+ }
+ }
+
+ return pselect6(nfd, r, w, e, mutableTimeout, kernelMask)
+}
+
/*
* Unimplemented
*/
diff --git a/unix/syscall_linux_test.go b/unix/syscall_linux_test.go
index 2787fe5..b854811 100644
--- a/unix/syscall_linux_test.go
+++ b/unix/syscall_linux_test.go
@@ -444,6 +444,40 @@
}
}
+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
+ }
+
+ for {
+ var sigmask unix.Sigset_t
+ sigmask.Val[0] |= 1 << (uint(unix.SIGUSR1) - 1)
+ 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()
diff --git a/unix/zsyscall_linux.go b/unix/zsyscall_linux.go
index 7ceec23..44e033a 100644
--- a/unix/zsyscall_linux.go
+++ b/unix/zsyscall_linux.go
@@ -1356,7 +1356,7 @@
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
+func pselect6(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *pselect6Sigset_t) (n int, err error) {
r0, _, e1 := Syscall6(SYS_PSELECT6, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)))
n = int(r0)
if e1 != 0 {
diff --git a/unix/ztypes_linux.go b/unix/ztypes_linux.go
index 02e2462..69f3eec 100644
--- a/unix/ztypes_linux.go
+++ b/unix/ztypes_linux.go
@@ -866,6 +866,11 @@
POLLNVAL = 0x20
)
+type pselect6Sigset_t struct {
+ ss *Sigset_t
+ ssLen uintptr
+}
+
type SignalfdSiginfo struct {
Signo uint32
Errno int32
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from:
Congratulations on opening your first change. Thank you for your contribution!
Next steps:
A maintainer will review your change and provide feedback. See
https://go.dev/doc/contribute#review for more info and tips to get your
patch through code review.
Most changes in the Go project go through a few rounds of revision. This can be
surprising to people new to the project. The careful, iterative review process
is our way of helping mentor contributors and ensuring that their contributions
have a lasting impact.
During May-July and Nov-Jan the Go project is in a code freeze, during which
little code gets reviewed or merged. If a reviewer responds with a comment like
R=go1.11 or adds a tag like "wait-release", it means that this CL will be
reviewed as part of the next development cycle. See https://go.dev/s/release
for more details.
Attention is currently required from: Brad Fitzpatrick, Ian Lance Taylor, Tobias Klauser.
3 comments:
File unix/syscall_linux.go:
Patch Set #1, Line 2442: // Per https://man7.org/linux/man-pages/man2/select.2.html#NOTES,
The Go `Pselect` wrapper never followed this requirement, which means this is a breaking change. I agree it was technically a bug, but it can break existing programs in hard-to-detect ways, particularly where EINTR is involved.
At the very least, it is not relevant to the fix at hand, so maybe split this to a separate issue.
Patch Set #1, Line 2458: // A sigset stores one bit per signal,
This comment really describes the calculation of `sigsetWords` above.
File unix/ztypes_linux.go:
Patch Set #1, Line 869: type pselect6Sigset_t struct {
For reference, the Linux kernel calls this `sigset_argpack`. (glibc itself uses an array of ulongs instead of a struct.) It might be helpful to use similar terminology.
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Brad Fitzpatrick, Ian Lance Taylor, Tobias Klauser.
Gerrit Bot uploaded patch set #2 to this change.
linux: fix last argument of pselect6
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: b77b37afefbcdc1a97fdef9415a0353346c2eb68
GitHub-Pull-Request: golang/sys#167
---
M unix/linux/types.go
M unix/syscall_linux.go
M unix/syscall_linux_test.go
M unix/zsyscall_linux.go
M unix/ztypes_linux.go
5 files changed, 76 insertions(+), 2 deletions(-)
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Brad Fitzpatrick, Ian Lance Taylor, Jesse Rittner, Tobias Klauser.
Patch set 2:Code-Review +1
2 comments:
File unix/syscall_linux.go:
The Go `Pselect` wrapper never followed this requirement, which means this is a breaking change. […]
This is relevant to #61251 in that it is fixing a documented difference between the POSIX function semantics and the kernel syscall ABI, and between the existing function's behavior on Linux and AIX.
Looking at the ~80 hits for this function on GitHub,¹ the vast majority are copies of the tests for this package. Of the handful that are not:
Those are all of the references I could find outside of `x/sys/unix` itself, and the only one that would be affected is the one that has been archived for nearly three years. I think this is ok to fix now.
¹https://github.com/search?q=language%3AGo+unix.Pselect&type=code
File unix/syscall_linux_amd64.go:
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Brad Fitzpatrick, Bryan Mills, Ian Lance Taylor, Jesse Rittner, Tobias Klauser.
Gerrit Bot uploaded patch set #3 to this change.
linux: fix last argument of pselect6
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: 29a4f6baba9c00c463352ae25f4cf588b74177b0
GitHub-Pull-Request: golang/sys#167
---
M unix/linux/types.go
M unix/syscall_linux.go
M unix/syscall_linux_amd64.go
M unix/syscall_linux_arm64.go
M unix/syscall_linux_loong64.go
M unix/syscall_linux_mips64x.go
M unix/syscall_linux_riscv64.go
M unix/syscall_linux_test.go
M unix/zsyscall_linux.go
M unix/ztypes_linux.go
10 files changed, 81 insertions(+), 7 deletions(-)
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Brad Fitzpatrick, Bryan Mills, Jesse Rittner, Mauri de Souza Meneguzzo, Tobias Klauser.
6 comments:
Commit Message:
Patch Set #3, Line 7: linux: fix last argument of pselect6
s/linux/unix/
Patch Set #3, Line 9: On Linux, the last argument of pselect6 system call is **not** a sigseg_t * pointer, but instead it is a structure of the form:
Please add a line break in this paragraph.
File unix/syscall_linux.go:
I ended up creating a follow up ticket as suggested here https://github.com/golang/go/issues/61402. […]
I think that Pselect, like Select, should not modify the timeout value.
We should document this in a function doc comment, though.
File unix/syscall_linux.go:
Patch Set #3, Line 2462: sigsetBytes := uintptr(sigsetWords * (wordBits / 8))
Seems simpler to set ssLen to unsafe.Sizeof(sigmask).
File unix/syscall_linux_amd64.go:
File unix/syscall_linux_test.go:
Patch Set #3, Line 464: for {
Why are there two loops? What additional testing is being done by the two variants of the loop? Whatever the answer is, there should be a comment in the code explaining it. Thanks.
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Brad Fitzpatrick, Ian Lance Taylor, Jesse Rittner, Mauri de Souza Meneguzzo, Tobias Klauser.
Patch set 3:Code-Review +1
1 comment:
File unix/syscall_linux.go:
Patch Set #3, Line 2462: sigsetBytes := uintptr(sigsetWords * (wordBits / 8))
Seems simpler to set ssLen to unsafe.Sizeof(sigmask).
That unfortunately doesn't work (see https://go.dev/issue/61251#issuecomment-1629868693). The `Sigset_t` type is generated from `type Sigset_t C.sigset_t`, which on Linux with `glibc` seems to be sized for up to 1024(!) (instead of `NSIG`) signals, but the kernel expects libc to pass an `ssLen` sized for exactly `NSIG`.
(The oversized glibc `sigset_t` appears to date to at least [1997](https://sourceware.org/git/?p=glibc.git;a=commit;f=sysdeps/unix/sysv/linux/sigset.h;h=df4ef2ab9c0899b2670067cd97e58f7eb2913e00). I'm not sure how much further back it goes.)
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Brad Fitzpatrick, Bryan Mills, Ian Lance Taylor, Jesse Rittner, Tobias Klauser.
3 comments:
File unix/syscall_linux.go:
This is relevant to #61251 in that it is fixing a documented difference between the POSIX function s […]
I ended up creating a follow up ticket as suggested here https://github.com/golang/go/issues/61402. Please let me know if I should close it.
I also think it is adequate to deal with this now, seems to be a rather unused low level function that is mostly used in x/sys.
Patch Set #1, Line 2458: // A sigset stores one bit per signal,
This comment really describes the calculation of `sigsetWords` above.
Done
File unix/ztypes_linux.go:
Patch Set #1, Line 869: type pselect6Sigset_t struct {
For reference, the Linux kernel calls this `sigset_argpack`. […]
Done
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Brad Fitzpatrick, Bryan Mills, Ian Lance Taylor, Jesse Rittner, Tobias Klauser.
1 comment:
File unix/syscall_linux_amd64.go:
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Brad Fitzpatrick, Bryan Mills, Ian Lance Taylor, Jesse Rittner, Mauri de Souza Meneguzzo, Tobias Klauser.
Gerrit Bot uploaded patch set #4 to this change.
unix: fix last argument of pselect6
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: 29a4f6baba9c00c463352ae25f4cf588b74177b0
GitHub-Pull-Request: golang/sys#167
---
M unix/linux/types.go
M unix/syscall_linux.go
M unix/syscall_linux_amd64.go
M unix/syscall_linux_arm64.go
M unix/syscall_linux_loong64.go
M unix/syscall_linux_mips64x.go
M unix/syscall_linux_riscv64.go
M unix/syscall_linux_test.go
M unix/zsyscall_linux.go
M unix/ztypes_linux.go
10 files changed, 81 insertions(+), 7 deletions(-)
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Brad Fitzpatrick, Bryan Mills, Ian Lance Taylor, Jesse Rittner, Tobias Klauser.
2 comments:
Commit Message:
Patch Set #3, Line 7: linux: fix last argument of pselect6
s/linux/unix/ […]
Done
Patch Set #3, Line 9: On Linux, the last argument of pselect6 system call is **not** a sigseg_t * pointer, but instead it is a structure of the form:
Please add a line break in this paragraph.
Done
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Brad Fitzpatrick, Bryan Mills, Ian Lance Taylor, Jesse Rittner, Tobias Klauser.
Gerrit Bot uploaded patch set #5 to this change.
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: 29a4f6baba9c00c463352ae25f4cf588b74177b0
GitHub-Pull-Request: golang/sys#167
---
M unix/linux/types.go
M unix/syscall_linux.go
M unix/syscall_linux_amd64.go
M unix/syscall_linux_arm64.go
M unix/syscall_linux_loong64.go
M unix/syscall_linux_mips64x.go
M unix/syscall_linux_riscv64.go
M unix/syscall_linux_test.go
M unix/zsyscall_linux.go
M unix/ztypes_linux.go
10 files changed, 81 insertions(+), 7 deletions(-)
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Brad Fitzpatrick, Bryan Mills, Ian Lance Taylor, Jesse Rittner, Tobias Klauser.
Patch Set #3, Line 464: for {
Why are there two loops? What additional testing is being done by the two variants of the loop? Wh […]
Sorry, this was a leftover, I just removed it.
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Brad Fitzpatrick, Bryan Mills, Ian Lance Taylor, Jesse Rittner, Tobias Klauser.
Gerrit Bot uploaded patch set #6 to this change.
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: 364d4d2fab1b4825fdb02d648214f43e7d2d1848
GitHub-Pull-Request: golang/sys#167
---
M unix/linux/types.go
M unix/syscall_linux.go
M unix/syscall_linux_amd64.go
M unix/syscall_linux_arm64.go
M unix/syscall_linux_loong64.go
M unix/syscall_linux_mips64x.go
M unix/syscall_linux_riscv64.go
M unix/syscall_linux_test.go
M unix/zsyscall_linux.go
M unix/ztypes_linux.go
10 files changed, 65 insertions(+), 7 deletions(-)
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Brad Fitzpatrick, Bryan Mills, Ian Lance Taylor, Jesse Rittner, Tobias Klauser.
Patch Set #3, Line 464: for {
Sorry, this was a leftover, I just removed it.
Done
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Brad Fitzpatrick, Bryan Mills, Ian Lance Taylor, Jesse Rittner, Tobias Klauser.
1 comment:
File unix/syscall_linux.go:
I think that Pselect, like Select, should not modify the timeout value. […]
Done
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Brad Fitzpatrick, Bryan Mills, Ian Lance Taylor, Jesse Rittner, Tobias Klauser.
Gerrit Bot uploaded patch set #7 to this change.
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: cb3c6d7da9b846843a4a81898ebfdcf2e449942a
GitHub-Pull-Request: golang/sys#167
---
M unix/linux/types.go
M unix/syscall_linux.go
M unix/syscall_linux_amd64.go
M unix/syscall_linux_arm64.go
M unix/syscall_linux_loong64.go
M unix/syscall_linux_mips64x.go
M unix/syscall_linux_riscv64.go
M unix/syscall_linux_test.go
M unix/zsyscall_linux.go
M unix/ztypes_linux.go
10 files changed, 67 insertions(+), 7 deletions(-)
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Brad Fitzpatrick, Bryan Mills, Jesse Rittner, Tobias Klauser.
1 comment:
File unix/syscall_linux.go:
Patch Set #3, Line 2462: sigsetBytes := uintptr(sigsetWords * (wordBits / 8))
That unfortunately doesn't work (see https://go.dev/issue/61251#issuecomment-1629868693). […]
Argh, thanks.
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Brad Fitzpatrick, Bryan Mills, Jesse Rittner, Tobias Klauser.
Patch set 7:Run-TryBot +1Auto-Submit +1Code-Review +2
1 comment:
Patchset:
Thanks.
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.
Gopher Robot submitted this change.
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: cb3c6d7da9b846843a4a81898ebfdcf2e449942a
GitHub-Pull-Request: golang/sys#167
Reviewed-on: https://go-review.googlesource.com/c/sys/+/510195
Reviewed-by: Bryan Mills <bcm...@google.com>
Reviewed-by: Ian Lance Taylor <ia...@google.com>
TryBot-Result: Gopher Robot <go...@golang.org>
Run-TryBot: Ian Lance Taylor <ia...@google.com>
Auto-Submit: Ian Lance Taylor <ia...@google.com>
---
M unix/linux/types.go
M unix/syscall_linux.go
M unix/syscall_linux_amd64.go
M unix/syscall_linux_arm64.go
M unix/syscall_linux_loong64.go
M unix/syscall_linux_mips64x.go
M unix/syscall_linux_riscv64.go
M unix/syscall_linux_test.go
M unix/zsyscall_linux.go
M unix/ztypes_linux.go
10 files changed, 67 insertions(+), 7 deletions(-)
diff --git a/unix/linux/types.go b/unix/linux/types.go
index 469ff6b..f2cbd2d 100644
--- a/unix/linux/types.go
+++ b/unix/linux/types.go
@@ -968,6 +968,10 @@
)
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
diff --git a/unix/syscall_linux.go b/unix/syscall_linux.go
index 332a74b..a730878 100644
--- a/unix/syscall_linux.go
+++ b/unix/syscall_linux.go
@@ -1885,7 +1885,7 @@
//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)
@@ -2438,6 +2438,39 @@
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
*/
diff --git a/unix/syscall_linux_amd64.go b/unix/syscall_linux_amd64.go
index 5b21fcf..70601ce 100644
--- a/unix/syscall_linux_amd64.go
+++ b/unix/syscall_linux_amd64.go
@@ -40,7 +40,7 @@
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)
diff --git a/unix/syscall_linux_arm64.go b/unix/syscall_linux_arm64.go
index a81f574..f526668 100644
--- a/unix/syscall_linux_arm64.go
+++ b/unix/syscall_linux_arm64.go
@@ -33,7 +33,7 @@
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)
diff --git a/unix/syscall_linux_loong64.go b/unix/syscall_linux_loong64.go
index 69d2d7c..f6ab02e 100644
--- a/unix/syscall_linux_loong64.go
+++ b/unix/syscall_linux_loong64.go
@@ -28,7 +28,7 @@
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)
diff --git a/unix/syscall_linux_mips64x.go b/unix/syscall_linux_mips64x.go
index 76d5640..93fe59d 100644
--- a/unix/syscall_linux_mips64x.go
+++ b/unix/syscall_linux_mips64x.go
@@ -31,7 +31,7 @@
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)
diff --git a/unix/syscall_linux_riscv64.go b/unix/syscall_linux_riscv64.go
index 35851ef..b1de100 100644
--- a/unix/syscall_linux_riscv64.go
+++ b/unix/syscall_linux_riscv64.go
@@ -32,7 +32,7 @@
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)
diff --git a/unix/syscall_linux_test.go b/unix/syscall_linux_test.go
index 2787fe5..dee8745 100644
--- a/unix/syscall_linux_test.go
+++ b/unix/syscall_linux_test.go
@@ -444,6 +444,24 @@
}
}
+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()
diff --git a/unix/zsyscall_linux.go b/unix/zsyscall_linux.go
index 7ceec23..a07321b 100644
--- a/unix/zsyscall_linux.go
+++ b/unix/zsyscall_linux.go
@@ -1356,7 +1356,7 @@
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
+func pselect6(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *sigset_argpack) (n int, err error) {
r0, _, e1 := Syscall6(SYS_PSELECT6, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)))
n = int(r0)
if e1 != 0 {
diff --git a/unix/ztypes_linux.go b/unix/ztypes_linux.go
index 02e2462..26ef52a 100644
--- a/unix/ztypes_linux.go
+++ b/unix/ztypes_linux.go
@@ -866,6 +866,11 @@
POLLNVAL = 0x20
)
+type sigset_argpack struct {
+ ss *Sigset_t
+ ssLen uintptr
+}
+
type SignalfdSiginfo struct {
Signo uint32
Errno int32
To view, visit change 510195. To unsubscribe, or for help writing mail filters, visit settings.