internal/pipewire: EPOLL_CTL_ADD instead of EPOLL_CTL_MOD
All checks were successful
Test / Create distribution (push) Successful in 37s
Test / Sandbox (push) Successful in 2m29s
Test / Hakurei (push) Successful in 3m24s
Test / Hpkg (push) Successful in 4m15s
Test / Sandbox (race detector) (push) Successful in 4m30s
Test / Hakurei (race detector) (push) Successful in 5m26s
Test / Flake checks (push) Successful in 1m45s
All checks were successful
Test / Create distribution (push) Successful in 37s
Test / Sandbox (push) Successful in 2m29s
Test / Hakurei (push) Successful in 3m24s
Test / Hpkg (push) Successful in 4m15s
Test / Sandbox (race detector) (push) Successful in 4m30s
Test / Hakurei (race detector) (push) Successful in 5m26s
Test / Flake checks (push) Successful in 1m45s
Implementation is no longer tied down by the limitations of SyscallConn. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -188,63 +188,57 @@ func (conn *unixConn) wantsEpoll() error {
|
|||||||
if !conn.epoll {
|
if !conn.epoll {
|
||||||
conn.epoll = true
|
conn.epoll = true
|
||||||
conn.epollFd, conn.epollErr = syscall.EpollCreate1(syscall.EPOLL_CLOEXEC)
|
conn.epollFd, conn.epollErr = syscall.EpollCreate1(syscall.EPOLL_CLOEXEC)
|
||||||
|
if conn.epollErr == nil {
|
||||||
|
if conn.epollErr = syscall.EpollCtl(conn.epollFd, syscall.EPOLL_CTL_ADD, conn.fd, &syscall.EpollEvent{
|
||||||
|
Events: syscall.EPOLLERR | syscall.EPOLLHUP,
|
||||||
|
Fd: int32(conn.fd),
|
||||||
|
}); conn.epollErr != nil {
|
||||||
|
_ = syscall.Close(conn.epollFd)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return conn.epollErr
|
return conn.epollErr
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait waits for a specific I/O event on fd and returns a function
|
// wait waits for a specific I/O event on fd. Caller must arrange for wantsEpoll
|
||||||
// that must be deferred by the caller regardless of error.
|
// to be called somewhere before wait is called.
|
||||||
func (conn *unixConn) wait(event uint32, errP *error) (cleanupFunc func()) {
|
func (conn *unixConn) wait(event uint32) (err error) {
|
||||||
if conn.timeout == 0 {
|
if conn.timeout == 0 {
|
||||||
return func() {}
|
return nil
|
||||||
}
|
}
|
||||||
deadline := time.Now().Add(conn.timeout)
|
deadline := time.Now().Add(conn.timeout)
|
||||||
conn.timeout = 0
|
conn.timeout = 0
|
||||||
|
|
||||||
if *errP = syscall.EpollCtl(conn.epollFd, syscall.EPOLL_CTL_ADD, conn.fd, &syscall.EpollEvent{
|
if err = syscall.EpollCtl(conn.epollFd, syscall.EPOLL_CTL_MOD, conn.fd, &syscall.EpollEvent{
|
||||||
Events: event | syscall.EPOLLERR | syscall.EPOLLHUP,
|
Events: event | syscall.EPOLLERR | syscall.EPOLLHUP,
|
||||||
Fd: int32(conn.fd),
|
Fd: int32(conn.fd),
|
||||||
}); *errP != nil {
|
}); err != nil {
|
||||||
return func() {}
|
|
||||||
} else {
|
|
||||||
cleanupFunc = func() {
|
|
||||||
// fd is guaranteed to remain valid while f executes but not after f returns
|
|
||||||
if epDelErr := syscall.EpollCtl(conn.epollFd, syscall.EPOLL_CTL_DEL, conn.fd, nil); epDelErr != nil && *errP == nil {
|
|
||||||
*errP = epDelErr
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for timeout := deadline.Sub(time.Now()); timeout > 0; timeout = deadline.Sub(time.Now()) {
|
for timeout := deadline.Sub(time.Now()); timeout > 0; timeout = deadline.Sub(time.Now()) {
|
||||||
if n, err := syscall.EpollWait(conn.epollFd, conn.epollBuf[:], int(timeout/time.Millisecond)); err != nil {
|
var n int
|
||||||
*errP = err
|
if n, err = syscall.EpollWait(conn.epollFd, conn.epollBuf[:], int(timeout/time.Millisecond)); err != nil {
|
||||||
return
|
return
|
||||||
} else {
|
}
|
||||||
|
|
||||||
switch n {
|
switch n {
|
||||||
case 1: // only the socket fd is ever added
|
case 1: // only the socket fd is ever added
|
||||||
if conn.epollBuf[0].Fd != int32(conn.fd) { // unreachable
|
if conn.epollBuf[0].Fd != int32(conn.fd) { // unreachable
|
||||||
err = syscall.ENOTRECOVERABLE
|
return syscall.ENOTRECOVERABLE
|
||||||
break
|
|
||||||
}
|
}
|
||||||
if conn.epollBuf[0].Events&event == event ||
|
if conn.epollBuf[0].Events&event == event ||
|
||||||
conn.epollBuf[0].Events&syscall.EPOLLERR|syscall.EPOLLHUP != 0 {
|
conn.epollBuf[0].Events&syscall.EPOLLERR|syscall.EPOLLHUP != 0 {
|
||||||
break
|
return nil
|
||||||
}
|
}
|
||||||
*errP = syscall.ETIME
|
err = syscall.ETIME
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case 0: // timeout
|
case 0: // timeout
|
||||||
err = syscall.ETIMEDOUT
|
return syscall.ETIMEDOUT
|
||||||
break
|
|
||||||
|
|
||||||
default: // unreachable
|
default: // unreachable
|
||||||
err = syscall.ENOTRECOVERABLE
|
return syscall.ENOTRECOVERABLE
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
*errP = err
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -254,9 +248,7 @@ func (conn *unixConn) wait(event uint32, errP *error) (cleanupFunc func()) {
|
|||||||
func (conn *unixConn) Recvmsg(p, oob []byte, flags int) (n, oobn, recvflags int, err error) {
|
func (conn *unixConn) Recvmsg(p, oob []byte, flags int) (n, oobn, recvflags int, err error) {
|
||||||
if err = conn.wantsEpoll(); err != nil {
|
if err = conn.wantsEpoll(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
} else if err = conn.wait(syscall.EPOLLIN); err != nil {
|
||||||
defer conn.wait(syscall.EPOLLIN, &err)()
|
|
||||||
if err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,9 +260,7 @@ func (conn *unixConn) Recvmsg(p, oob []byte, flags int) (n, oobn, recvflags int,
|
|||||||
func (conn *unixConn) Sendmsg(p, oob []byte, flags int) (n int, err error) {
|
func (conn *unixConn) Sendmsg(p, oob []byte, flags int) (n int, err error) {
|
||||||
if err = conn.wantsEpoll(); err != nil {
|
if err = conn.wantsEpoll(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
} else if err = conn.wait(syscall.EPOLLOUT); err != nil {
|
||||||
defer conn.wait(syscall.EPOLLOUT, &err)()
|
|
||||||
if err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user