使用 syscall 时,我的事件轮询模型崩溃。Epoll事件

My event poll model crashes when using syscall.EpollEvent

提问人:alfiver 提问时间:6/29/2023 最后编辑:JBirdVegasalfiver 更新时间:6/29/2023 访问量:36

问:

in syscall/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 */
};

我想要

type evData struct {
    fd        int
    evHandler EvHandler
}
ev := syscall.EpollEvent{
    Events: syscall.EPOLLIN,
}
*(**evData)(unsafe.Pointer(&ev.Fd)) = ed

使用以下方式将内存区域以下转换为内存syscall.EpollEvent.Fdepoll_data_t.ptrunsafe.Pointer

经过测试,少量客户端请求没有问题。但是,当并发级别增加时,它会立即崩溃并引发内存异常。

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?})
    /usr/local/go/src/runtime/panic.go:1047 +0x5d fp=0xc00004bd50 sp=0xc00004bd20 pc=0x43213d
runtime.sigpanic()
    /usr/local/go/src/runtime/signal_unix.go:851 +0x28a fp=0xc00004bdb0 sp=0xc00004bd50 pc=0x44674a
github.com/shaovie/goev.(*evPoll).poll(0xc00005a040, 0x0, 0x0)
    /root/go/src/github.com/shaovie/goev/epoll.go:202 +0x3e7 fp=0xc00004be68 sp=0xc00004bdb0 pc=0x473dc7
github.com/shaovie/goev.(*evPoll).run(0xc00005a040)

为什么? 实现的代码可以在 (https://github.com/shaovie/goev/blob/main/epoll.go 中找到)

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
}

我从中复制了实现,但它仍然崩溃。runtime/netpoll_epoll.go

epoll

评论


答: 暂无答案