// epollinit opens an epoll file descriptor and creates a pipe which will be // used to wake up the epoll_wait(2) function. Then, file descriptor associated // with inotify event queue and the read end of the pipe are added to epoll set. // Note that `fd` member must be set before this function is called. func (i *inotify) epollinit() (err error) { if i.epfd, err = syscall.EpollCreate1(0); err != nil { return } if err = syscall.Pipe(i.pipefd); err != nil { return } i.epes = []syscall.EpollEvent{ {Events: syscall.EPOLLIN, Fd: i.fd}, {Events: syscall.EPOLLIN, Fd: int32(i.pipefd[0])}, } if err = syscall.EpollCtl(i.epfd, syscall.EPOLL_CTL_ADD, int(i.fd), &i.epes[0]); err != nil { return } return syscall.EpollCtl(i.epfd, syscall.EPOLL_CTL_ADD, i.pipefd[0], &i.epes[1]) }
func (p *pollster) StopWaiting(fd int, bits uint) { events, already := p.events[fd] if !already { print("Epoll unexpected fd=", fd, "\n") return } // If syscall.EPOLLONESHOT is not set, the wait // is a repeating wait, so don't change it. if events&syscall.EPOLLONESHOT == 0 { return } // Disable the given bits. // If we're still waiting for other events, modify the fd // event in the kernel. Otherwise, delete it. events &= ^uint32(bits) if int32(events)&^syscall.EPOLLONESHOT != 0 { var ev syscall.EpollEvent ev.Fd = int32(fd) ev.Events = events if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &ev); e != 0 { print("Epoll modify fd=", fd, ": ", os.Errno(e).String(), "\n") } p.events[fd] = events } else { if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != 0 { print("Epoll delete fd=", fd, ": ", os.Errno(e).String(), "\n") } p.events[fd] = 0, false } }
func (p *pollster) StopWaiting(fd int, bits uint) { // pollServer is locked. events, already := p.events[fd] if !already { // The fd returned by the kernel may have been // cancelled already; return silently. return } // If syscall.EPOLLONESHOT is not set, the wait // is a repeating wait, so don't change it. if events&syscall.EPOLLONESHOT == 0 { return } // Disable the given bits. // If we're still waiting for other events, modify the fd // event in the kernel. Otherwise, delete it. events &= ^uint32(bits) if int32(events)&^syscall.EPOLLONESHOT != 0 { p.ctlEvent.Fd = int32(fd) p.ctlEvent.Events = events if err := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &p.ctlEvent); err != nil { print("Epoll modify fd=", fd, ": ", err.Error(), "\n") } p.events[fd] = events } else { if err := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); err != nil { print("Epoll delete fd=", fd, ": ", err.Error(), "\n") } delete(p.events, fd) } }
func (io *NetIOManager) ProxyNetAccept(serverinfo syscall.Sockaddr) (sa syscall.Sockaddr, err error) { var clientfd, serverfd int // accpet mongodb client connection request clientfd, clientinfo, err := syscall.Accept(io.proxy_server_fd) if err != nil { goto ClientError } err = syscall.SetNonblock(clientfd, true) if err != nil { goto ClientCleanup } err = syscall.EpollCtl(io.epoll_fd, syscall.EPOLL_CTL_ADD, clientfd, &syscall.EpollEvent{Events: syscall.EPOLLIN | syscall.EPOLLOUT | syscall.EPOLLRDHUP, Fd: int32(clientfd)}) if err != nil { goto ClientCleanup } // establish connection with mongodb server serverfd, err = syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) if err != nil { goto ServerError } err = syscall.Connect(serverfd, serverinfo) if err != nil { goto ServerCleanup } err = syscall.SetNonblock(serverfd, true) if err != nil { goto ServerCleanup } err = syscall.EpollCtl(io.epoll_fd, syscall.EPOLL_CTL_ADD, serverfd, &syscall.EpollEvent{Events: syscall.EPOLLIN | syscall.EPOLLOUT | syscall.EPOLLRDHUP, Fd: int32(serverfd)}) if err != nil { goto ServerCleanup } // now proxy server becomes a bridge between client <-> server add_sock_peer(io, clientfd, clientinfo, serverfd, serverinfo) return clientinfo, nil ServerCleanup: syscall.Close(serverfd) ServerError: syscall.EpollCtl(io.epoll_fd, syscall.EPOLL_CTL_DEL, clientfd, &syscall.EpollEvent{Events: syscall.EPOLLIN | syscall.EPOLLOUT | syscall.EPOLLRDHUP, Fd: int32(clientfd)}) ClientCleanup: syscall.Close(clientfd) ClientError: return nil, err }
func (fd *FD) closeUnlocked() error { // Caller MUST already hold the C lock. Take the both R and W // locks, to exclude Read and Write operations from accessing // a closed sysfd. fd.r.cond.L.Lock() fd.w.cond.L.Lock() fd.closed = true // ev is not used by EpollCtl/DEL. Just don't pass a nil // pointer. var ev syscall.EpollEvent err := syscall.EpollCtl(epfd, syscall.EPOLL_CTL_DEL, fd.sysfd, &ev) if err != nil { log.Printf("poller: EpollCtl/DEL (fd=%d, sysfd=%d): %s", fd.id, fd.sysfd, err.Error()) } if fd.r.timer != nil { fd.r.timer.Stop() } if fd.w.timer != nil { fd.w.timer.Stop() } fdM.DelFD(fd.id) err = syscall.Close(fd.sysfd) // Wake up everybody waiting on the FD. fd.r.cond.Broadcast() fd.w.cond.Broadcast() debugf("FD %03d: CL: close(sysfd=%d)", fd.id, fd.sysfd) fd.w.cond.L.Unlock() fd.r.cond.L.Unlock() return err }
func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) { // pollServer is locked. var already bool p.ctlEvent.Fd = int32(fd) p.ctlEvent.Events, already = p.events[fd] if !repeat { p.ctlEvent.Events |= syscall.EPOLLONESHOT } if mode == 'r' { p.ctlEvent.Events |= readFlags } else { p.ctlEvent.Events |= writeFlags } var op int if already { op = syscall.EPOLL_CTL_MOD } else { op = syscall.EPOLL_CTL_ADD } if e := syscall.EpollCtl(p.epfd, op, fd, &p.ctlEvent); e != nil { return false, os.NewSyscallError("epoll_ctl", e) } p.events[fd] = p.ctlEvent.Events return false, nil }
func (p *pollster) AddFD(fd int, mode int, repeat bool) os.Error { var ev syscall.EpollEvent var already bool ev.Fd = int32(fd) ev.Events, already = p.events[fd] if !repeat { ev.Events |= syscall.EPOLLONESHOT } if mode == 'r' { ev.Events |= readFlags } else { ev.Events |= writeFlags } var op int if already { op = syscall.EPOLL_CTL_MOD } else { op = syscall.EPOLL_CTL_ADD } if e := syscall.EpollCtl(p.epfd, op, fd, &ev); e != 0 { return os.NewSyscallError("epoll_ctl", e) } p.events[fd] = ev.Events return nil }
func (io *NetIOManager) ProxyNetListen(sa syscall.Sockaddr) error { serverfd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) if err != nil { goto Error } err = syscall.Bind(serverfd, sa) if err != nil { goto Cleanup } err = syscall.Listen(serverfd, io.max_backlog) if err != nil { goto Cleanup } err = syscall.EpollCtl(io.epoll_fd, syscall.EPOLL_CTL_ADD, serverfd, &syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(serverfd)}) if err != nil { goto Cleanup } io.proxy_server_fd = serverfd return nil Cleanup: syscall.Close(serverfd) Error: return err }
func registerInterrupt(pin *digitalPin, handler func(embd.DigitalPin)) error { l := getEpollListenerInstance() pinFd := int(pin.val.Fd()) l.mu.Lock() defer l.mu.Unlock() if _, ok := l.interruptablePins[pinFd]; ok { return ErrorPinAlreadyRegistered } var event syscall.EpollEvent event.Events = syscall.EPOLLIN | (syscall.EPOLLET & 0xffffffff) | syscall.EPOLLPRI if err := syscall.SetNonblock(pinFd, true); err != nil { return err } event.Fd = int32(pinFd) if err := syscall.EpollCtl(l.fd, syscall.EPOLL_CTL_ADD, pinFd, &event); err != nil { return err } l.interruptablePins[pinFd] = &interrupt{pin: pin, handler: handler} return nil }
func newFD(sysfd int) (*FD, error) { // Set sysfd to non-blocking mode err := syscall.SetNonblock(sysfd, true) if err != nil { debugf("FD xxx: NF: sysfd=%d, err=%v", sysfd, err) return nil, err } // Initialize FD fd := &FD{sysfd: sysfd} fd.id = fdM.GetID() fd.r.cond = sync.NewCond(&fd.r.mu) fd.w.cond = sync.NewCond(&fd.w.mu) // Add to Epoll set. We may imediatelly start receiving events // after this. They will be dropped since the FD is not yet in // fdMap. It's ok. Nobody is waiting on this FD yet, anyway. ev := syscall.EpollEvent{ Events: syscall.EPOLLIN | syscall.EPOLLOUT | syscall.EPOLLRDHUP | (syscall.EPOLLET & 0xffffffff), Fd: int32(fd.id)} err = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd.sysfd, &ev) if err != nil { debugf("FD %03d: NF: sysfd=%d, err=%v", fd.id, fd.sysfd, err) return nil, err } // Add to fdMap fdM.AddFD(fd) debugf("FD %03d: NF: sysfd=%d", fd.id, fd.sysfd) return fd, nil }
func (p *pin) BeginWatch(edge Edge, callback IRQEvent) error { p.SetMode(ModeInput) if err := write([]byte(edge), p.edgePath); err != nil { return err } var event syscall.EpollEvent event.Events = syscall.EPOLLIN | (syscall.EPOLLET & 0xffffffff) | syscall.EPOLLPRI fd := int(p.valueFile.Fd()) p.callback = callback watchEventCallbacks[fd] = p if err := syscall.SetNonblock(fd, true); err != nil { return err } event.Fd = int32(fd) if err := syscall.EpollCtl(epollFD, syscall.EPOLL_CTL_ADD, fd, &event); err != nil { return err } return nil }
func (gpio *GPIO) DisableEdgeDetection() { epollFd := gpio.epollFd.Swap(0) if epollFd != 0 { syscall.EpollCtl(epollFd, syscall.EPOLL_CTL_DEL, int(gpio.valueFile.Fd()), new(syscall.EpollEvent)) syscall.Close(epollFd) } gpio.setEdge(EDGE_NONE) }
func sock_close(io *NetIOManager, fd int) { syscall.EpollCtl(io.epoll_fd, syscall.EPOLL_CTL_DEL, fd, &syscall.EpollEvent{Events: syscall.EPOLLIN | syscall.EPOLLOUT | syscall.EPOLLRDHUP, Fd: int32(fd)}) syscall.Close(fd) delete(io.pending_output_skbs, fd) delete(io.io_socket_peers, fd) }
func (ep *EPoll) AddFD(fd int, events uint32) error { ev := syscall.EpollEvent{ Events: events, Fd: int32(fd), } return syscall.EpollCtl(ep.fd, syscall.EPOLL_CTL_ADD, fd, &ev) }
// Add registers a socket for sending and/or receiving. The caller can't // access the socket directly after this. The send channel (if any) should be // closed by the caller. func (io *IO) Add(s *zmq.Socket, send <-chan Data, recv chan<- Data) (err error) { fd, err := s.GetFd() if err != nil { return } w := newWorker() io.lock.Lock() io.workers[int32(fd)] = w io.lock.Unlock() defer func() { if err != nil { io.lock.Lock() delete(io.workers, int32(fd)) io.lock.Unlock() } }() e := &syscall.EpollEvent{ Events: syscall.EPOLLIN | syscall.EPOLLET&0xffffffff, Fd: int32(fd), } if err = syscall.EpollCtl(io.epollFd, syscall.EPOLL_CTL_ADD, fd, e); err != nil { return } state, err := s.GetEvents() if err != nil { syscall.EpollCtl(io.epollFd, syscall.EPOLL_CTL_DEL, fd, nil) return } go func() { defer s.Close() defer syscall.EpollCtl(io.epollFd, syscall.EPOLL_CTL_DEL, fd, nil) w.socketLoop(s, send, recv, state) }() return }
// Create a new inotify poller. // This creates an inotify handler, and an epoll handler. func newFdPoller(fd int) (*fdPoller, error) { var errno error poller := emptyPoller(fd) defer func() { if errno != nil { poller.close() } }() poller.fd = fd // Create epoll fd poller.epfd, errno = syscall.EpollCreate1(0) if poller.epfd == -1 { return nil, errno } // Create pipe; pipe[0] is the read end, pipe[1] the write end. errno = syscall.Pipe2(poller.pipe[:], syscall.O_NONBLOCK) if errno != nil { return nil, errno } // Register inotify fd with epoll event := syscall.EpollEvent{ Fd: int32(poller.fd), Events: syscall.EPOLLIN, } errno = syscall.EpollCtl(poller.epfd, syscall.EPOLL_CTL_ADD, poller.fd, &event) if errno != nil { return nil, errno } // Register pipe fd with epoll event = syscall.EpollEvent{ Fd: int32(poller.pipe[0]), Events: syscall.EPOLLIN, } errno = syscall.EpollCtl(poller.epfd, syscall.EPOLL_CTL_ADD, poller.pipe[0], &event) if errno != nil { return nil, errno } return poller, nil }
func (gpio *GPIO) AddEdgeDetect(edge GPIOEdge) (chan bool, error) { gpio.RemoveEdgeDetect() err := gpio.SetDirection(GPIO_INPUT) if err != nil { return nil, err } err = gpio.SetEdge(edge) if err != nil { return nil, err } err = gpio.openValueFile() if err != nil { return nil, err } epfd, err := syscall.EpollCreate(1) if err != nil { return nil, err } event := &syscall.EpollEvent{ Events: syscall.EPOLLIN | _EPOLLET | syscall.EPOLLPRI, Fd: int32(gpio.value.Fd()), } err = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, int(gpio.value.Fd()), event) if err != nil { syscall.Close(epfd) return nil, err } // / first time triggers with current state, so ignore _, err = syscall.EpollWait(epfd, make([]syscall.EpollEvent, 1), -1) if err != nil { syscall.Close(epfd) return nil, err } gpio.epfd.Set(epfd) valueChan := make(chan bool) go func() { for gpio.epfd.Get() != 0 { n, _ := syscall.EpollWait(epfd, make([]syscall.EpollEvent, 1), -1) if n > 0 { value, err := gpio.Value() if err == nil { valueChan <- value } } } }() return valueChan, nil }
// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. func NewWatcher() (*Watcher, error) { fd, errno := syscall.InotifyInit() if fd == -1 { return nil, os.NewSyscallError("inotify_init", errno) } w := &Watcher{ fd: fd, watches: make(map[string]*watch), paths: make(map[int]string), Events: make(chan Event), Errors: make(chan error), done: make(chan bool), closed: make(chan bool), } w.cv = sync.NewCond(&w.mu) rp, wp, err := os.Pipe() // for done if err != nil { return nil, err } epfd, err := syscall.EpollCreate1(0) if err != nil { return nil, os.NewSyscallError("epoll_create1", err) } event := &syscall.EpollEvent{syscall.EPOLLIN, int32(w.fd), 0} if err = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, w.fd, event); err != nil { return nil, os.NewSyscallError("epoll_ctl", err) } event = &syscall.EpollEvent{syscall.EPOLLIN, int32(rp.Fd()), 0} if err = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, int(rp.Fd()), event); err != nil { return nil, os.NewSyscallError("epoll_ctl", err) } go func() { <-w.done wp.Close() // make rp readable }() go w.epollEvents(epfd, rp) return w, nil }
func New(fd int) (p *Poller, err error) { p = &Poller{} if p.epfd, err = syscall.EpollCreate1(0); err != nil { return nil, err } p.event.Events = syscall.EPOLLOUT p.event.Fd = int32(fd) if err = syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_ADD, fd, &p.event); err != nil { p.Close() return nil, err } return p, nil }
func (m *Monitor) start() { var events [128]syscall.EpollEvent for { n, err := archutils.EpollWait(m.epollFd, events[:], -1) if err != nil { if err == syscall.EINTR { continue } logrus.WithField("error", err).Fatal("containerd: epoll wait") } // process events for i := 0; i < n; i++ { fd := int(events[i].Fd) m.m.Lock() r := m.receivers[fd] switch t := r.(type) { case runtime.Process: if events[i].Events == syscall.EPOLLHUP { delete(m.receivers, fd) if err = syscall.EpollCtl(m.epollFd, syscall.EPOLL_CTL_DEL, fd, &syscall.EpollEvent{ Events: syscall.EPOLLHUP, Fd: int32(fd), }); err != nil { logrus.WithField("error", err).Error("containerd: epoll remove fd") } if err := t.Close(); err != nil { logrus.WithField("error", err).Error("containerd: close process IO") } EpollFdCounter.Dec(1) m.exits <- t } case runtime.OOM: // always flush the event fd t.Flush() if t.Removed() { delete(m.receivers, fd) // epoll will remove the fd from its set after it has been closed t.Close() EpollFdCounter.Dec(1) } else { m.ooms <- t.ContainerID() } } m.m.Unlock() } } }
// EndWatch stops watching the pin func (p *pin) EndWatch() error { fd := int(p.valueFile.Fd()) if err := syscall.EpollCtl(epollFD, syscall.EPOLL_CTL_DEL, fd, nil); err != nil { return err } if err := syscall.SetNonblock(fd, false); err != nil { return err } delete(watchEventCallbacks, fd) return nil }
func (gpio *GPIO) WaitForEdge(edge Edge) (value Value, err error) { if err = gpio.setEdge(edge); err != nil { return 0, err } if err = gpio.ensureValueFileIsOpen(); err != nil { return 0, err } epollFd := gpio.epollFd.Get() if epollFd == 0 { epollFd, err = syscall.EpollCreate(1) if err != nil { return 0, err } event := &syscall.EpollEvent{ Events: syscall.EPOLLIN | syscall.EPOLLPRI | _EPOLLET, Fd: int32(gpio.valueFile.Fd()), } err = syscall.EpollCtl(epollFd, syscall.EPOLL_CTL_ADD, int(gpio.valueFile.Fd()), event) if err != nil { syscall.Close(epollFd) return 0, err } // first time triggers with current state, so ignore _, err = syscall.EpollWait(epollFd, dummyEpollEvents, -1) if err != nil { syscall.Close(epollFd) return 0, err } gpio.epollFd.Set(epollFd) } _, err = syscall.EpollWait(epollFd, dummyEpollEvents, -1) if err != nil { return 0, err } return gpio.Value() }
func init_inotify() { var err error name_by_wd = make(map[int32]string) wd_by_name = make(map[string]int32) var event syscall.InotifyEvent event_size = int(unsafe.Sizeof(event)) inotify_fd, _ = syscall.InotifyInit() if -1 == inotify_fd { bump_message("InotifyInit failed, file changes outside of tabby " + "will remain unnoticed") return } epoll_fd, err = syscall.EpollCreate(1) if -1 == epoll_fd { tabby_log("init_inotify: " + err.Error()) } var epoll_event syscall.EpollEvent epoll_event.Events = syscall.EPOLLIN syscall.EpollCtl(epoll_fd, syscall.EPOLL_CTL_ADD, inotify_fd, &epoll_event) go inotify_observe() }
func unregisterInterrupt(pin *digitalPin) error { l := getEpollListenerInstance() pinFd := int(pin.val.Fd()) l.mu.Lock() defer l.mu.Unlock() if _, ok := l.interruptablePins[pinFd]; !ok { return nil } if err := syscall.EpollCtl(l.fd, syscall.EPOLL_CTL_DEL, pinFd, nil); err != nil { return err } if err := syscall.SetNonblock(pinFd, false); err != nil { return err } delete(l.interruptablePins, pinFd) return nil }
func DialTCPTimeoutWithMD5Sig(host string, port int, localAddr, key string, msec int) (*net.TCPConn, error) { var family int var ra, la syscall.Sockaddr ip, err := net.ResolveIPAddr("ip", host) if err != nil { return nil, fmt.Errorf("invalid ip: %s", err) } l, err := net.ResolveIPAddr("ip", localAddr) if l == nil { return nil, fmt.Errorf("invalid local ip: %s", err) } if (ip.IP.To4() != nil) != (l.IP.To4() != nil) { return nil, fmt.Errorf("remote and local ip address family is not same") } switch { case ip.IP.To4() != nil: family = syscall.AF_INET i := &syscall.SockaddrInet4{ Port: port, } for idx, _ := range i.Addr { i.Addr[idx] = ip.IP.To4()[idx] } ra = i j := &syscall.SockaddrInet4{} for idx, _ := range j.Addr { j.Addr[idx] = l.IP.To4()[idx] } la = j default: family = syscall.AF_INET6 i := &syscall.SockaddrInet6{ Port: port, } for idx, _ := range i.Addr { i.Addr[idx] = ip.IP[idx] } ra = i var zone uint32 if l.Zone != "" { intf, err := net.InterfaceByName(l.Zone) if err != nil { return nil, err } zone = uint32(intf.Index) } j := &syscall.SockaddrInet6{ ZoneId: zone, } for idx, _ := range j.Addr { j.Addr[idx] = l.IP[idx] } la = j } sotype := syscall.SOCK_STREAM | syscall.SOCK_CLOEXEC | syscall.SOCK_NONBLOCK proto := 0 fd, err := syscall.Socket(family, sotype, proto) if err != nil { return nil, err } fi := os.NewFile(uintptr(fd), "") defer fi.Close() t, err := buildTcpMD5Sig(host, key) if err != nil { return nil, err } if _, _, e := syscall.Syscall6(syscall.SYS_SETSOCKOPT, uintptr(fd), uintptr(syscall.IPPROTO_TCP), uintptr(TCP_MD5SIG), uintptr(unsafe.Pointer(&t)), unsafe.Sizeof(t), 0); e > 0 { return nil, os.NewSyscallError("setsockopt", e) } if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1); err != nil { return nil, os.NewSyscallError("setsockopt", err) } if err = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, 1); err != nil { return nil, os.NewSyscallError("setsockopt", err) } if err = syscall.Bind(fd, la); err != nil { return nil, os.NewSyscallError("bind", err) } tcpconn := func(fi *os.File) (*net.TCPConn, error) { conn, err := net.FileConn(fi) return conn.(*net.TCPConn), err } err = syscall.Connect(fd, ra) switch err { case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: // do timeout handling case nil, syscall.EISCONN: return tcpconn(fi) default: return nil, os.NewSyscallError("connect", err) } epfd, e := syscall.EpollCreate1(syscall.EPOLL_CLOEXEC) if e != nil { return nil, e } defer syscall.Close(epfd) var event syscall.EpollEvent events := make([]syscall.EpollEvent, 1) event.Events = syscall.EPOLLIN | syscall.EPOLLOUT | syscall.EPOLLPRI event.Fd = int32(fd) if e = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event); e != nil { return nil, e } for { nevents, e := syscall.EpollWait(epfd, events, msec) if e != nil { return nil, e } if nevents == 0 { return nil, fmt.Errorf("timeout") } else if nevents == 1 && events[0].Fd == int32(fd) { nerr, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_ERROR) if err != nil { return nil, os.NewSyscallError("getsockopt", err) } switch err := syscall.Errno(nerr); err { case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: case syscall.Errno(0), syscall.EISCONN: return tcpconn(fi) default: return nil, os.NewSyscallError("getsockopt", err) } } else { return nil, fmt.Errorf("unexpected epoll behavior") } } }
func (u *NetLinkProbe) start() { s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK) if err != nil { logging.GetLogger().Errorf("Failed to subscribe to netlink RTNLGRP_LINK messages: %s", err.Error()) return } u.nlSocket = s defer u.nlSocket.Close() fd := u.nlSocket.GetFd() err = syscall.SetNonblock(fd, true) if err != nil { logging.GetLogger().Errorf("Failed to set the netlink fd as non-blocking: %s", err.Error()) return } epfd, e := syscall.EpollCreate1(0) if e != nil { logging.GetLogger().Errorf("Failed to create epoll: %s", err.Error()) return } defer syscall.Close(epfd) u.initialize() event := syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(fd)} if e = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event); e != nil { logging.GetLogger().Errorf("Failed to control epoll: %s", err.Error()) return } events := make([]syscall.EpollEvent, maxEpollEvents) for u.running.Load() == true { n, err := syscall.EpollWait(epfd, events[:], 1000) if err != nil { errno, ok := err.(syscall.Errno) if ok && errno != syscall.EINTR { logging.GetLogger().Errorf("Failed to receive from events from netlink: %s", err.Error()) } continue } if n == 0 { continue } msgs, err := s.Receive() if err != nil { logging.GetLogger().Errorf("Failed to receive from netlink messages: %s", err.Error()) time.Sleep(1 * time.Second) continue } for _, msg := range msgs { switch msg.Header.Type { case syscall.RTM_NEWLINK: ifmsg := nl.DeserializeIfInfomsg(msg.Data) u.onLinkAdded(int(ifmsg.Index)) case syscall.RTM_DELLINK: ifmsg := nl.DeserializeIfInfomsg(msg.Data) u.onLinkDeleted(int(ifmsg.Index)) } } } }
func doParent(mpid int, stdin_fd, stdout_fd, stderr_fd [2]int) resultPack { syscall.Close(stdin_fd[0]) syscall.Close(stdout_fd[1]) syscall.Close(stderr_fd[1]) exit_chan := make(chan resultPack) if err := SetupScope(uint32(mpid)); err != nil { poePanic(err, "setup systemd scope unit failed") } go func() { runtime.LockOSThread() sig_chan := make(chan os.Signal, 1) signal.Notify(sig_chan, syscall.SIGCHLD) signal.Notify(sig_chan, syscall.SIGTERM) signal.Notify(sig_chan, syscall.SIGINT) if err := PtraceSeize(mpid, syscall.PTRACE_O_TRACECLONE|syscall.PTRACE_O_TRACEFORK|PTRACE_O_TRACESECCOMP|syscall.PTRACE_O_TRACEVFORK); err != nil { poePanic(error(err), "PTRACE_SEIZE failed") } for { sig := <-sig_chan switch sig { case syscall.SIGCHLD: if res := handleSigchld(mpid); res != nil { exit_chan <- *res } case syscall.SIGTERM, syscall.SIGINT: exit_chan <- resultPack{POE_TIMEDOUT, -1, "Supervisor terminated"} } } }() // TODO: output order is not preserved out_chan := make(chan childOutput, 1) go func() { epfd, err := syscall.EpollCreate1(0) if err != nil { poePanic(err, "epoll_create1 failed") } defer syscall.Close(epfd) event1 := syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(stdout_fd[0]), Pad: 1} // Fd/Pad is epoll_data_t (userdata) if err := syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, stdout_fd[0], &event1); err != nil { poePanic(err, "epoll_ctl (EPOLL_CTL_ADD) failed") } event2 := syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(stderr_fd[0]), Pad: 2} if err := syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, stderr_fd[0], &event2); err != nil { poePanic(err, "epoll_ctl (EPOLL_CTL_ADD) failed") } var events [32]syscall.EpollEvent for { en, err := syscall.EpollWait(epfd, events[:], -1) if err != nil { poePanic(err, "epoll_wait failed") } var buf [65536]byte // TODO: how to get PIPE_BUF? for ev := 0; ev < en; ev++ { for { n, err := syscall.Read(int(events[ev].Fd), buf[:]) if err != nil { break } if n > 0 { nbuf := make([]byte, n) copy(nbuf, buf[:n]) out_chan <- childOutput{int(events[ev].Pad), n, nbuf} } } } } }() go func() { for { out := <-out_chan var outbuf bytes.Buffer binary.Write(&outbuf, binary.LittleEndian, int32(out.fd)) binary.Write(&outbuf, binary.LittleEndian, int32(out.n)) if _, err := os.Stdout.Write(outbuf.Bytes()); err != nil { poePanic(err, "stdout write failed") } if _, err := os.Stdout.Write(out.buf); err != nil { poePanic(err, "stdout write failed") } } }() go func() { <-time.After(3 * time.Second) exit_chan <- resultPack{POE_TIMEDOUT, -1, ""} }() if _, err := syscall.Write(stdin_fd[1], []byte{0}); err != nil { poePanic(err, "write to stdin failed") } return <-exit_chan }
func main() { flag.Parse() if SHOWVER { fmt.Println("Version:", VERSION) return } debug("Phoenix Guest Agent started [pid=" + fmt.Sprintf("%d", os.Getpid()) + "]") port, err := OpenPort(PORTPATH) if err != nil { log.Fatalln("Failed to open character device:", err) } defer port.Close() epollFd, err := syscall.EpollCreate1(0) if err != nil { log.Fatalln("Error creating epoll:", err) } defer syscall.Close(epollFd) ctlEvent := syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(port.fd)} if err := syscall.EpollCtl(epollFd, syscall.EPOLL_CTL_ADD, int(port.fd), &ctlEvent); err != nil { log.Fatalln("Error registering epoll event:", err) } reader := bufio.NewReader(port.f) cReq := make(chan []byte) cResp := make(chan *Response, 1) lock := false for { if !lock { lock = true go listenPort(cReq, epollFd, reader) } select { case jsonReq := <-cReq: lock = false req := &Request{} if err := json.Unmarshal(jsonReq, &req); err != nil { debug("JSON parse error:", err) port.SendError(fmt.Errorf("JSON parse error: %s", err), "") continue } switch req.Command { case "ping": port.SendResponse(VERSION, req.Tag) continue case "agent-shutdown": debug("Shutdown command received from client") return case "get-commands": go GetCommandList(cResp, req.Tag) continue } if FROZEN && req.Command != "get-freeze-status" && req.Command != "fs-unfreeze" { debug("All filesystems are frozen. Cannot execute:", req.Command) port.SendError(fmt.Errorf("All filesystems are frozen. Cannot execute: %s", req.Command), req.Tag) continue } if _, ok := Commands[req.Command]; !ok { debug("Unknown command:", req.Command) port.SendError(fmt.Errorf("Unknown command: %s", req.Command), req.Tag) continue } debug("Processing command:", req.Command+", tag =", req.Tag) go Commands[req.Command](cResp, req.RawArgs, req.Tag) case resp := <-cResp: if resp.Err != nil { port.SendError(resp.Err, resp.Tag) } else { port.SendResponse(resp.Value, resp.Tag) } } // end of select } }
return err }}, { ErrFmt: "Bind epoll fd error [%s]\n", Action: func(t *Tunnel) error { return syscall.Bind(t.LFd, &syscall.SockaddrInet4{Port: int(t.EPort), Addr: [4]byte{0, 0, 0, 0}}) }}, { ErrFmt: "Listen fd error [%s]\n", Action: func(t *Tunnel) error { return syscall.Listen(t.LFd, 10) }}, { ErrFmt: "Add fd to epoll error [%s]\n", Action: func(t *Tunnel) error { return syscall.EpollCtl(epollFd, syscall.EPOLL_CTL_ADD, t.LFd, &syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(t.LFd)}) }}, } var pathAddStep = [...]TunnelStep{ { ErrFmt: "Port [%d] accept error [%s]", Action: func(tc *TunnelConn) (err error) { tc.EFd, _, err = syscall.Accept(tc.RelTunnel.LFd) return }}, { ErrFmt: "Port [%d] set fd nonblock error [%s]", Action: func(tc *TunnelConn) (err error) { return syscall.SetNonblock(tc.EFd, true) }},
// EpollCtl directly calls syscall.EpollCtl func EpollCtl(epfd int, op int, fd int, event *syscall.EpollEvent) error { return syscall.EpollCtl(epfd, op, fd, event) }