in ztypes_linux_amd64.go
type EpollEvent struct {
Events uint32
Fd int32
Pad int32
}
man 2 epoll_ctl
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
struct epoll_event {
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
I want
type evData struct {
fd int
evHandler EvHandler
}
ev := syscall.EpollEvent{
Events: syscall.EPOLLIN,
}
*(**evData)(unsafe.Pointer(&ev.Fd)) = ed
Convert the memory area following syscall.EpollEvent.Fd into epoll_data_t.ptr memory using unsafe.Pointer
After testing, there are no issues with a small number of client requests. However, when the concurrency level increases, it immediately crashes and throws a memory exception.
unexpected fault address 0x1018
fatal error: fault
[signal SIGSEGV: segmentation violation code=0x1 addr=0x1018 pc=0x473dc7]
goroutine 1 [running, locked to thread]:
runtime.throw({0x48c50d?, 0xc00004bda0?})
panic.go:1047 +0x5d fp=0xc00004bd50 sp=0xc00004bd20 pc=0x43213d
runtime.sigpanic()
signal_unix.go:851 +0x28a fp=0xc00004bdb0 sp=0xc00004bd50 pc=0x44674a
goev.(*evPoll).poll(0xc00005a040, 0x0, 0x0)
epoll.go:202 +0x3e7 fp=0xc00004be68 sp=0xc00004bdb0 pc=0x473dc7
goev.(*evPoll).run(0xc00005a040)
why ?
The implemented code can be found at (goev/epoll.go at main · shaovie/goev · GitHub)
var (
_zero uintptr
)
type epollEvent struct {
Events uint32
Fd [8]byte
}
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return nil
case unix.EAGAIN:
return syscall.EAGAIN
case unix.EINVAL:
return syscall.EINVAL
case unix.ENOENT:
return syscall.ENOENT
}
return e
}
func epollWait(epfd int, events []epollEvent, msec int) (n int, err error) {
var _p0 unsafe.Pointer
if len(events) > 0 {
_p0 = unsafe.Pointer(&events[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := unix.Syscall6(unix.SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
func epollCtl(epfd int, op int, fd int, event *epollEvent) (err error) {
_, _, e1 := unix.RawSyscall6(unix.SYS_EPOLL_CTL, uintptr(epfd), uintptr(op), uintptr(fd), uintptr(unsafe.Pointer(event)), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
I copied the implementation from runtime.netpoll_epoll.go, but it still crashes.