Improve darwin forwarding

This commit is contained in:
世界 2026-07-08 19:38:44 +08:00
parent dcfbe83ca6
commit b0188bc3f1
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
4 changed files with 116 additions and 56 deletions

View file

@ -69,7 +69,7 @@ func NonBlockingWriteIovec(fd int, iovec []unix.Iovec) unix.Errno {
return e
}
func BlockingReadvUntilStopped(efd int, fd int, iovecs []unix.Iovec) (int, unix.Errno) {
func BlockingReadvUntilStopped(poller *Poller, fd int, iovecs []unix.Iovec) (int, unix.Errno) {
for {
//nolint:staticcheck
n, _, e := unix.RawSyscall(unix.SYS_READV, uintptr(fd), uintptr(unsafe.Pointer(&iovecs[0])), uintptr(len(iovecs)))
@ -79,7 +79,7 @@ func BlockingReadvUntilStopped(efd int, fd int, iovecs []unix.Iovec) (int, unix.
if e != 0 && e != unix.EWOULDBLOCK {
return 0, e
}
stopped, e := BlockingPollUntilStopped(efd, fd, unix.POLLIN)
stopped, e := poller.Wait()
if stopped {
return -1, e
}
@ -89,7 +89,7 @@ func BlockingReadvUntilStopped(efd int, fd int, iovecs []unix.Iovec) (int, unix.
}
}
func BlockingRecvMMsgUntilStopped(efd int, fd int, msgHdrs []MsgHdrX) (int, unix.Errno) {
func BlockingRecvMMsgUntilStopped(poller *Poller, fd int, msgHdrs []MsgHdrX) (int, unix.Errno) {
for {
//nolint:staticcheck
n, _, e := unix.RawSyscall6(unix.SYS_RECVMSG_X, uintptr(fd), uintptr(unsafe.Pointer(&msgHdrs[0])), uintptr(len(msgHdrs)), unix.MSG_DONTWAIT, 0, 0)
@ -101,7 +101,7 @@ func BlockingRecvMMsgUntilStopped(efd int, fd int, msgHdrs []MsgHdrX) (int, unix
return 0, e
}
stopped, e := BlockingPollUntilStopped(efd, fd, unix.POLLIN)
stopped, e := poller.Wait()
if stopped {
return -1, e
}
@ -111,71 +111,58 @@ func BlockingRecvMMsgUntilStopped(efd int, fd int, msgHdrs []MsgHdrX) (int, unix
}
}
func BlockingPollUntilStopped(efd int, fd int, events int16) (bool, unix.Errno) {
// Create kqueue
type Poller struct {
kq int
efd int
fd int
}
func NewPoller(efd int, fd int) (*Poller, error) {
kq, err := unix.Kqueue()
if err != nil {
return false, unix.Errno(err.(unix.Errno))
return nil, err
}
defer unix.Close(kq)
// Prepare kevents for registration
var kevents []unix.Kevent_t
// Always monitor efd for read events
kevents = append(kevents, unix.Kevent_t{
Ident: uint64(efd),
Filter: unix.EVFILT_READ,
Flags: unix.EV_ADD | unix.EV_ENABLE,
})
// Monitor fd based on requested events
// Convert poll events to kqueue filters
if events&unix.POLLIN != 0 {
kevents = append(kevents, unix.Kevent_t{
kevents := []unix.Kevent_t{
{
Ident: uint64(efd),
Filter: unix.EVFILT_READ,
Flags: unix.EV_ADD | unix.EV_ENABLE,
},
{
Ident: uint64(fd),
Filter: unix.EVFILT_READ,
Flags: unix.EV_ADD | unix.EV_ENABLE,
})
},
}
if events&unix.POLLOUT != 0 {
kevents = append(kevents, unix.Kevent_t{
Ident: uint64(fd),
Filter: unix.EVFILT_WRITE,
Flags: unix.EV_ADD | unix.EV_ENABLE,
})
}
// Register events
_, err = unix.Kevent(kq, kevents, nil, nil)
if err != nil {
return false, unix.Errno(err.(unix.Errno))
unix.Close(kq)
return nil, err
}
return &Poller{kq: kq, efd: efd, fd: fd}, nil
}
// Wait for events (blocking)
revents := make([]unix.Kevent_t, len(kevents))
n, err := unix.Kevent(kq, nil, revents, nil)
func (p *Poller) Wait() (bool, unix.Errno) {
var revents [2]unix.Kevent_t
n, err := unix.Kevent(p.kq, nil, revents[:], nil)
if err != nil {
return false, unix.Errno(err.(unix.Errno))
return false, err.(unix.Errno)
}
// Check results
var efdHasData bool
var errno unix.Errno
for i := range n {
ev := &revents[i]
if int(ev.Ident) == efd && ev.Filter == unix.EVFILT_READ {
if int(ev.Ident) == p.efd && ev.Filter == unix.EVFILT_READ {
efdHasData = true
}
if int(ev.Ident) == fd {
// Check for errors or EOF
if int(ev.Ident) == p.fd {
if ev.Flags&unix.EV_EOF != 0 {
errno = unix.ECONNRESET
} else if ev.Flags&unix.EV_ERROR != 0 {
// Extract error from Data field
if ev.Data != 0 {
errno = unix.Errno(ev.Data)
} else {
@ -187,3 +174,7 @@ func BlockingPollUntilStopped(efd int, fd int, events int16) (bool, unix.Errno)
return efdHasData, errno
}
func (p *Poller) Close() error {
return unix.Close(p.kq)
}