|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"log"
|
|
|
|
"syscall"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
EPOLLET = 1 << 31
|
|
|
|
)
|
|
|
|
|
|
|
|
func (s *server) epollWatch(fd int) error {
|
|
|
|
event := syscall.EpollEvent{
|
|
|
|
Fd: int32(fd),
|
|
|
|
Events: syscall.EPOLLHUP | EPOLLET,
|
|
|
|
}
|
|
|
|
return syscall.EpollCtl(s.epfd, syscall.EPOLL_CTL_ADD, fd, &event)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *server) epollDelete(fd int) error {
|
|
|
|
return syscall.EpollCtl(s.epfd, syscall.EPOLL_CTL_DEL, fd, &syscall.EpollEvent{})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *server) handleEpoll() {
|
|
|
|
events := make([]syscall.EpollEvent, 1024)
|
|
|
|
for {
|
|
|
|
n, errno := syscall.EpollWait(s.epfd, events, -1)
|
|
|
|
if n == -1 {
|
|
|
|
if errno == syscall.EINTR {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
log.Fatalf("connection cleaner: epoll wait failed with %v", errno)
|
|
|
|
}
|
|
|
|
ready := events[:n]
|
|
|
|
for _, event := range ready {
|
|
|
|
if event.Events&(syscall.EPOLLHUP|syscall.EPOLLERR) != 0 {
|
|
|
|
if err := s.epollDelete(int(event.Fd)); err != nil && !errors.Is(err, syscall.ENOENT) {
|
|
|
|
log.Printf("failed to remove socket from epoll: %s", err)
|
|
|
|
}
|
|
|
|
s.connectionClosed <- int(event.Fd)
|
|
|
|
} else {
|
|
|
|
log.Printf("Unhandled epoll event: %d for fd %d", event.Events, event.Fd)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|