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 }
// setupEpoll sets up epoll for use func setupEpoll() { var err error epollFD, err = syscall.EpollCreate1(0) if err != nil { fmt.Println("Unable to create epoll FD: ", err.Error()) os.Exit(1) } go func() { var epollEvents [GPIOCount]syscall.EpollEvent for { numEvents, err := syscall.EpollWait(epollFD, epollEvents[:], -1) if err != nil { panic(fmt.Sprintf("EpollWait error: %s", err.Error())) } for i := 0; i < numEvents; i++ { if eventPin, exists := watchEventCallbacks[int(epollEvents[i].Fd)]; exists { if eventPin.initial { eventPin.initial = false } else { eventPin.callback() } } } } }() }
/*----------------------------------------------------------------------------- -- FUNCTION: listen -- -- DATE: February 6, 2016 -- -- REVISIONS: February 10, 2016 - Modified for EPoll -- -- DESIGNER: Marc Vouve -- -- PROGRAMMER: Marc Vouve -- -- INTERFACE: func listen(srvInfo serverInfo) -- srvInfo: information about the overall application, IPC and networking -- -- RETURNS: void doesn't actually return. -- -- NOTES: This function handles Epoll in a foreverloop. This function never -- exits ------------------------------------------------------------------------------*/ func listen(srvInfo serverInfo) { client := make(map[int]connectionInfo) epollFd, _ := syscall.EpollCreate1(0) events := make([]syscall.EpollEvent, epollQueueLen) addConnectionToEPoll(epollFd, srvInfo.listener) for { n, _ := syscall.EpollWait(epollFd, events[:], -1) for i := 0; i < n; i++ { if events[i].Events&(syscall.EPOLLHUP|syscall.EPOLLERR) != 0 { fmt.Println("Error on epoll") endConnection(srvInfo, client[int(events[i].Fd)]) } if events[i].Fd == int32(srvInfo.listener) { // new connection newClient, err := newConnection(srvInfo.listener) if err == nil { srvInfo.serverConnection <- newConnectionConst client[newClient.FileDescriptor] = newClient addConnectionToEPoll(epollFd, newClient.FileDescriptor) } } else { // data to read from connection // client[int(ev.Fd)] can not be used as an argument in handleData conn := client[int(events[i].Fd)] err := handleData(&conn) client[int(events[i].Fd)] = conn if err != nil { endConnection(srvInfo, client[int(events[i].Fd)]) } } } } }
func initEpollListener() *epollListener { fd, err := syscall.EpollCreate1(0) if err != nil { panic(fmt.Sprintf("Unable to create epoll: %v", err)) } listener := &epollListener{fd: fd, interruptablePins: make(map[int]*interrupt)} go func() { var epollEvents [MaxGPIOInterrupt]syscall.EpollEvent for { n, err := syscall.EpollWait(listener.fd, epollEvents[:], -1) if err != nil { panic(fmt.Sprintf("EpollWait error: %v", err)) } listener.mu.Lock() for i := 0; i < n; i++ { if irq, ok := listener.interruptablePins[int(epollEvents[i].Fd)]; ok { irq.Signal() } } listener.mu.Unlock() } }() return listener }
// loop blocks until either inotify or pipe file descriptor is ready for I/O. // All read operations triggered by filesystem notifications are forwarded to // one of the event's consumers. If pipe fd became ready, loop function closes // all file descriptors opened by lazyinit method and returns afterwards. func (i *inotify) loop(esch chan<- []*event) { epes := make([]syscall.EpollEvent, 1) fd := atomic.LoadInt32(&i.fd) for { switch _, err := syscall.EpollWait(i.epfd, epes, -1); err { case nil: switch epes[0].Fd { case fd: esch <- i.read() epes[0].Fd = 0 case int32(i.pipefd[0]): i.Lock() defer i.Unlock() if err = syscall.Close(int(fd)); err != nil && err != syscall.EINTR { panic("notify: close(2) error " + err.Error()) } atomic.StoreInt32(&i.fd, invalidDescriptor) if err = i.epollclose(); err != nil && err != syscall.EINTR { panic("notify: epollclose error " + err.Error()) } close(esch) return } case syscall.EINTR: continue default: // We should never reach this line. panic("notify: epoll_wait(2) error " + err.Error()) } } }
func listenPort(cReq chan<- []byte, epollFd int, reader *bufio.Reader) { events := make([]syscall.EpollEvent, 32) var buf []byte var err error for { if _, err := syscall.EpollWait(epollFd, events, -1); err != nil { log.Fatalln("Error receiving epoll events:", err) } buf, err = reader.ReadBytes('\x0a') switch err { case nil: case io.EOF: time.Sleep(time.Second * 1) continue default: log.Fatalln(err) } break } cReq <- buf }
func (ep *EPoll) Poll(timeout int) (int, error) { nfds, err := syscall.EpollWait(ep.fd, ep.events[0:], timeout) if err != nil { return 0, err } ep.nfds = nfds return nfds, 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 (p *pollster) WaitFD(nsec int64) (fd int, mode int, err os.Error) { // Get an event. var evarray [1]syscall.EpollEvent ev := &evarray[0] var msec int = -1 if nsec > 0 { msec = int((nsec + 1e6 - 1) / 1e6) } n, e := syscall.EpollWait(p.epfd, evarray[0:], msec) for e == syscall.EAGAIN || e == syscall.EINTR { n, e = syscall.EpollWait(p.epfd, evarray[0:], msec) } if e != 0 { return -1, 0, os.NewSyscallError("epoll_wait", e) } if n == 0 { return -1, 0, nil } fd = int(ev.Fd) if ev.Events&writeFlags != 0 { p.StopWaiting(fd, writeFlags) return fd, 'w', nil } if ev.Events&readFlags != 0 { p.StopWaiting(fd, readFlags) return fd, 'r', nil } // Other events are error conditions - wake whoever is waiting. events, _ := p.events[fd] if events&writeFlags != 0 { p.StopWaiting(fd, writeFlags) return fd, 'w', nil } p.StopWaiting(fd, readFlags) return fd, 'r', nil }
func (p *Poller) WaitWrite(deadline time.Time) error { msec := -1 if !deadline.IsZero() { d := deadline.Sub(time.Now()) msec = int(d.Nanoseconds() / 1000000) // ms!? omg... } n, err := syscall.EpollWait(p.epfd, p.events[:], msec) if err != nil { return err } if n < 1 { return errTimeout } return nil }
func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) { for len(p.waitEvents) == 0 { var msec int = -1 if nsec > 0 { msec = int((nsec + 1e6 - 1) / 1e6) } s.Unlock() n, e := syscall.EpollWait(p.epfd, p.waitEventBuf[0:], msec) s.Lock() if e != nil { if e == syscall.EAGAIN || e == syscall.EINTR { continue } return -1, 0, os.NewSyscallError("epoll_wait", e) } if n == 0 { return -1, 0, nil } p.waitEvents = p.waitEventBuf[0:n] } ev := &p.waitEvents[0] p.waitEvents = p.waitEvents[1:] fd = int(ev.Fd) if ev.Events&writeFlags != 0 { p.StopWaiting(fd, writeFlags) return fd, 'w', nil } if ev.Events&readFlags != 0 { p.StopWaiting(fd, readFlags) return fd, 'r', nil } // Other events are error conditions - wake whoever is waiting. events, _ := p.events[fd] if events&writeFlags != 0 { p.StopWaiting(fd, writeFlags) return fd, 'w', nil } p.StopWaiting(fd, readFlags) return fd, 'r', nil }
func Run(t *Tunnel) { var err error epollFd, err = syscall.EpollCreate(1024) if err != nil { logger.Log(logger.ERR, "Create epoll fd error [%s]", err) os.Exit(-2) } for _, step := range initStep { err = step.Action(t) if err != nil { fmt.Fprintf(os.Stderr, step.ErrFmt, err) os.Exit(-2) } } runTunnel = t events := make([]syscall.EpollEvent, 10, 10) for { en, err := syscall.EpollWait(epollFd, events, 1000) if err != nil { logger.Log(logger.ERR, "Wail epoll fd error [%s]", err) os.Exit(-2) } for i := 0; i < en; i++ { ee := events[i] if runTunnel.LFd == int(ee.Fd) { runTunnel.newConn() continue } tc, ok := fdTunnelConn[int(ee.Fd)] if !ok { continue } if ee.Events&syscall.EPOLLIN != 0 { tc.handleIn(int(ee.Fd)) } if ee.Events&syscall.EPOLLOUT != 0 { tc.handleOut(int(ee.Fd)) } if ee.Events&syscall.EPOLLHUP != 0 { tc.shutdown() } } } }
func inotify_observe_collect(buf []byte) map[string]int { epoll_buf := make([]syscall.EpollEvent, 1) collect := make(map[string]int) for { nread, _ := syscall.Read(inotify_fd, buf) for offset := 0; offset < nread; offset += event_size { event := (*syscall.InotifyEvent)(unsafe.Pointer(&buf[offset])) if syscall.IN_IGNORED == event.Mask { continue } collect[name_by_wd[event.Wd]] = 1 } nevents, err := syscall.EpollWait(epoll_fd, epoll_buf, 500) if 0 >= nevents { if -1 == nevents { tabby_log("inotify_observe_collect: " + err.Error()) } break } } return collect }
func poller() { debugf("Started.") events := make([]syscall.EpollEvent, 128) for { n, err := syscall.EpollWait(epfd, events, -1) if err != nil { if err == syscall.EINTR { continue } log.Panicf("poller: EpollWait: %s", err.Error()) } for i := 0; i < n; i++ { ev := &events[i] if isReadEvent(ev) { epollEvent(ev, false) } if isWriteEvent(ev) { epollEvent(ev, true) } } } }
func (w *Watcher) epollEvents(epfd int, donePipe *os.File) { w.isRunning = true defer func() { syscall.Close(epfd) w.isRunning = false w.closed <- true }() events := make([]syscall.EpollEvent, EPOLL_MAX_EVENTS) doneFd := int32(donePipe.Fd()) for { nevents, err := syscall.EpollWait(epfd, events, -1) if err != nil { w.Errors <- os.NewSyscallError("epoll_wait", err) continue } if nevents == 0 { continue } for i := 0; i < nevents; i++ { if events[i].Fd == doneFd { if err = donePipe.Close(); err != nil { w.Errors <- err } syscall.Close(w.fd) close(w.Events) close(w.Errors) return } else if events[i].Fd != int32(w.fd) { continue } if err = w.readEvents(); err != nil { w.Errors <- err } } } }
func (io *IO) eventLoop() { const mask = syscall.EPOLLIN | syscall.EPOLLERR | syscall.EPOLLHUP buf := make([]syscall.EpollEvent, epollEventBufferSize) for { n, err := syscall.EpollWait(io.epollFd, buf, -1) if err != nil { panic(err) } io.lock.Lock() for _, e := range buf[:n] { if e.Events&mask != 0 { if w := io.workers[e.Fd]; w != nil { w.notify() } } } io.lock.Unlock() } }
func (u *NetLinkProbe) start(nsPath string) { var context *common.NetNSContext var err error // Enter the network namespace if necessary if nsPath != "" { context, err = common.NewNetNsContext(nsPath) if err != nil { logging.GetLogger().Errorf("Failed to switch namespace: %s", err.Error()) return } } // Both NewHandle and Subscribe need to done in the network namespace. h, err := netlink.NewHandle(syscall.NETLINK_ROUTE) if err != nil { logging.GetLogger().Errorf("Failed to create netlink handle: %s", err.Error()) context.Close() return } defer h.Delete() s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK, syscall.RTNLGRP_IPV4_IFADDR, syscall.RTNLGRP_IPV6_IFADDR) if err != nil { logging.GetLogger().Errorf("Failed to subscribe to netlink messages: %s", err.Error()) context.Close() return } defer s.Close() u.ethtool, err = ethtool.NewEthtool() if err != nil { logging.GetLogger().Errorf("Failed to create ethtool object: %s", err.Error()) context.Close() return } defer u.ethtool.Close() epfd, e := syscall.EpollCreate1(0) if e != nil { logging.GetLogger().Errorf("Failed to create epoll: %s", err.Error()) return } defer syscall.Close(epfd) // Leave the network namespace context.Close() u.wg.Add(1) defer u.wg.Done() atomic.StoreInt64(&u.state, common.RunningState) defer atomic.StoreInt64(&u.state, common.StoppedState) u.netlink = h u.initialize() fd := s.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 } event := syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(fd)} if err = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event); err != nil { logging.GetLogger().Errorf("Failed to control epoll: %s", err.Error()) return } events := make([]syscall.EpollEvent, maxEpollEvents) for atomic.LoadInt64(&u.state) == common.RunningState { 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 { if errno, ok := err.(syscall.Errno); !ok || !errno.Temporary() { logging.GetLogger().Errorf("Failed to receive from netlink messages: %s", err.Error()) return } time.Sleep(1 * time.Second) continue } for _, msg := range msgs { switch msg.Header.Type { case syscall.RTM_NEWLINK: link, err := netlink.LinkDeserialize(msg.Data) if err != nil { logging.GetLogger().Warningf("Failed to deserialize netlink message: %s", err.Error()) continue } u.onLinkAdded(link) case syscall.RTM_DELLINK: link, err := netlink.LinkDeserialize(msg.Data) if err != nil { logging.GetLogger().Warningf("Failed to deserialize netlink message: %s", err.Error()) continue } u.onLinkDeleted(link) case syscall.RTM_NEWADDR: addr, family, ifindex, err := parseAddr(msg.Data) if err != nil { logging.GetLogger().Warningf("Failed to parse newlink message: %s", err.Error()) continue } u.onAddressAdded(addr, family, ifindex) case syscall.RTM_DELADDR: addr, family, ifindex, err := parseAddr(msg.Data) if err != nil { logging.GetLogger().Warningf("Failed to parse newlink message: %s", err.Error()) continue } u.onAddressDeleted(addr, family, ifindex) } } } }
func (watcher *PinWatcher) pinHandler() { exf, exf_err := os.OpenFile("/sys/class/gpio/export", syscall.O_WRONLY, 0400) if exf_err != nil { log.Panicln("Error opening /sys/class/gpio/export:", exf_err) } _, ex_err := exf.WriteString(fmt.Sprintf("%d", watcher.pin)) if ex_err != nil { log.Panicln("Error writing to /sys/class/gpio/export:", ex_err) } exf.Close() time.Sleep(time.Microsecond) edge_file := fmt.Sprintf("/sys/class/gpio/gpio%d/edge", watcher.pin) edgef, edgef_err := os.OpenFile(edge_file, syscall.O_WRONLY, 0400) if edgef_err != nil { log.Panicf("Error opening %s: %s\n", edge_file, edgef_err) } _, edge_err := edgef.WriteString("both") if edge_err != nil { log.Panicf("Error writing to %s: %s\n", edge_file, edge_err) } edgef.Close() time.Sleep(time.Microsecond) value_file := fmt.Sprintf("/sys/class/gpio/gpio%d/value", watcher.pin) irq_fd, irq_err := syscall.Open(value_file, syscall.O_RDONLY|syscall.O_NONBLOCK, syscall.S_IREAD) if irq_err != nil { log.Panicln("Error opening %s: %s\n", value_file, irq_err) } epfd, eperr := syscall.EpollCreate1(syscall.EPOLL_CLOEXEC) if eperr != nil { log.Panicln("Error creating epoll:", eperr) } event := new(syscall.EpollEvent) event.Fd = int32(irq_fd) event.Events |= syscall.EPOLLPRI if ctlerr := syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, irq_fd, event); ctlerr != nil { log.Panicln("Error on epoll control operation:", ctlerr) } var events_buffer [10]syscall.EpollEvent var buf [1]byte for !watcher.shutdown { n, werr := syscall.EpollWait(epfd, events_buffer[0:], 4000) if werr != nil { log.Println("Epoll error:", werr) } else if n == 1 { syscall.Seek(irq_fd, 0, 0) syscall.Read(irq_fd, buf[0:]) log.Println("Interrupt!", events_buffer[0].Fd, events_buffer[0].Events, buf) } else { log.Println("Timeout") } } syscall.Close(irq_fd) unexf, unexf_err := os.OpenFile("/sys/class/gpio/unexport", syscall.O_WRONLY|syscall.O_SYNC, 0400) if unexf_err != nil { log.Panicln("Error opening /sys/class/gpio/unexport:", unexf_err) } _, unex_err := unexf.WriteString(fmt.Sprintf("%d", watcher.pin)) if unex_err != nil { log.Panicln("Error writing to /sys/class/gpio/unexport:", unex_err) } unexf.Close() watcher.wg.Done() }
func (self HciDev) Request(opcode OpCode, params ...Parameter) (Parameters, error) { req := make([]byte, 4) req[0] = HCI_COMMAND_PKT binary.LittleEndian.PutUint16(req[1:], uint16(opcode)) if pbuf, err := Parameters(params).MarshalBinary(); err != nil { return nil, err } else { req[3] = uint8(len(pbuf)) req = append(req, pbuf...) } if filter, err := GetsockoptHciFilter(int(self), SOL_HCI, HCI_FILTER); err != nil { return nil, err } else { defer SetsockoptHciFilter(int(self), SOL_HCI, HCI_FILTER, filter) } filter := &HciFilter{ Type_mask: 1 << HCI_EVENT_PKT, Event_mask: FilterEventMask(EVT_CMD_STATUS, EVT_CMD_COMPLETE), Opcode: opcode.Native(), } if opcode.Ogf() == OGF_LE_CTL { filter.Event_mask = FilterEventMask(EVT_CMD_STATUS, EVT_CMD_COMPLETE, EVT_LE_META_EVENT) } if err := SetsockoptHciFilter(int(self), SOL_HCI, HCI_FILTER, filter); err != nil { return nil, err } if n, err := self.Write(req); err != nil { return nil, err } else if n != len(req) { return nil, fmt.Errorf("write incomplete") } if efd, err := syscall.EpollCreate1(syscall.EPOLL_CLOEXEC); err != nil { return nil, err } else { defer syscall.Close(efd) var events [1]syscall.EpollEvent syscall.EpollCtl(efd, syscall.EPOLL_CTL_ADD, int(self), &syscall.EpollEvent{ Events: syscall.EPOLLIN, Fd: int32(self), }) capture := make([]byte, 0, 258) buf := make([]byte, 258) for { if n, err := syscall.EpollWait(efd, events[:], 100); err != nil { return nil, err } else if n == 0 { continue } // todo: operation timeout if n, _, _, _, err := syscall.Recvmsg(int(self), buf, nil, syscall.MSG_DONTWAIT); err != nil { if errno, ok := err.(syscall.Errno); ok && errno.Temporary() { continue } return nil, err } else if n == 0 { continue } else { capture = append(capture, buf[:n]...) } if pkt, step := Parse(capture); step == 0 { continue } else if p, err := pkt.(EventPkt).Parse(); err != nil { continue } else { switch ev := p.(type) { case EvtCmdComplete: if ev.OpCode == uint16(opcode) { return opcode.Response(ev.Params) } case EvtCmdStatus: if ev.OpCode == uint16(opcode) && ev.Status != 0 { return nil, HciError(ev.Status) } case EvtLeMetaEvent: // todo: OGF_LE_CTL opcode expects this } capture = capture[step:] } } return nil, fmt.Errorf("should not reach") } }
// EpollWait directly calls syscall.EpollWait func EpollWait(epfd int, events []syscall.EpollEvent, msec int) (int, error) { return syscall.EpollWait(epfd, events, msec) }
func (u *NetLinkTopoUpdater) start() { logging.GetLogger().Debug("Start NetLink Topo Updater for container: %s", u.Container.ID) s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK) if err != nil { logging.GetLogger().Error("Failed to subscribe to netlink RTNLGRP_LINK messages: %s", err.Error()) return } u.nlSocket = s fd := u.nlSocket.GetFd() err = syscall.SetNonblock(fd, true) if err != nil { logging.GetLogger().Error("Failed to set the netlink fd as non-blocking: %s", err.Error()) return } epfd, e := syscall.EpollCreate1(0) if e != nil { logging.GetLogger().Error("Failed to set the netlink fd as non-blocking: %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().Error("Failed to set the netlink fd as non-blocking: %s", err.Error()) return } events := make([]syscall.EpollEvent, maxEpollEvents) Loop: for { n, err := syscall.EpollWait(epfd, events[:], 1000) if err != nil { logging.GetLogger().Error("Failed to receive from netlink messages: %s", err.Error()) continue } if n == 0 { select { case <-u.doneChan: logging.GetLogger().Debug("WHOU") break Loop default: continue } } msgs, err := s.Receive() if err != nil { logging.GetLogger().Error("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)) } } } u.nlSocket.Close() }
func NewFdset() *Fdset { self := &Fdset{ rListener: make(map[int]fdListener), wListener: make(map[int]fdListener), rDeadline: make(map[int]time.Time), wDeadline: make(map[int]time.Time), } efd, e1 := syscall.EpollCreate1(syscall.EPOLL_CLOEXEC) if e1 != nil { return nil } ctls, e2 := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, 0) if e2 != nil { return nil } self.ctl = ctls[0] self.rListener[ctls[1]] = fdDrain(ctls[1]) go func() { defer func() { syscall.Close(ctls[1]) self.Close() }() evs := make([]syscall.EpollEvent, 8) for { fds := make(map[int]uint32) for fd, _ := range self.rListener { fds[fd] |= syscall.EPOLLIN } for fd, _ := range self.wListener { fds[fd] |= syscall.EPOLLOUT } if len(fds) == 0 { break } have_tm := false var tm time.Time for _, t := range self.rDeadline { if !have_tm || t.Before(tm) { tm = t } have_tm = true } for _, t := range self.wDeadline { if !have_tm || t.Before(tm) { tm = t } have_tm = true } for fd, flags := range fds { if err := syscall.EpollCtl(efd, syscall.EPOLL_CTL_ADD, fd, &syscall.EpollEvent{ Events: flags, Fd: int32(fd), }); err != nil { if fd == int(ctls[1]) { // maybe ctrl closed return } else { log.Print(err) delete(fds, fd) } } } dur := time.Hour if have_tm { dur = tm.Sub(time.Now()) } evLen := 0 if dur > 0 { if n, err := syscall.EpollWait(efd, evs, int(dur/time.Millisecond)); err != nil { if eno, ok := err.(syscall.Errno); !ok || !eno.Temporary() { // notify fdset poll loop error for _, li := range self.wListener { li.FdListen(err) } for _, li := range self.rListener { li.FdListen(err) } return } } else { evLen = n } } if len(self.wDeadline) > 0 || len(self.rDeadline) > 0 { tm := time.Now() for fd, t := range self.wDeadline { if li, ok := self.wListener[fd]; ok { if t.Before(tm) { if !li.FdListen(Timeout(t)) { delete(self.wListener, fd) } delete(self.wDeadline, fd) } } } for fd, t := range self.rDeadline { if li, ok := self.rListener[fd]; ok { if t.Before(tm) { if !li.FdListen(Timeout(t)) { delete(self.rListener, fd) } delete(self.rDeadline, fd) } } } } for _, ev := range evs[:evLen] { if ev.Events&syscall.EPOLLOUT != 0 { if li, ok := self.wListener[int(ev.Fd)]; ok { if !li.FdListen(nil) { delete(self.wListener, int(ev.Fd)) } delete(self.wDeadline, int(ev.Fd)) } } if ev.Events&syscall.EPOLLIN != 0 { if li, ok := self.rListener[int(ev.Fd)]; ok { if !li.FdListen(nil) { delete(self.rListener, int(ev.Fd)) } delete(self.rDeadline, int(ev.Fd)) } } } for fd, _ := range fds { if err := syscall.EpollCtl(efd, syscall.EPOLL_CTL_DEL, fd, nil); err != nil { panic(err) } } } }() return self }
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 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 StartProxyServer(conf *ProxyConfig, proxy_log l4g.Logger) (err error) { logger = proxy_log var filter *IOFilterProtocol var netio *NetIOManager proxy := &ProxyServer{ max_listen_fds: 1024, timeout: 1000, quit: false, epoll_fd: -1, events: make([]syscall.EpollEvent, 100), sighnd: make(chan os.Signal, 1), } if !parse_config(proxy, conf) { logger.Error("Failed to initialize proxy server.") goto Error } filter = NewIOFilterProtocol(conf) if filter == nil { logger.Error("Failed to initialize filter protocol.") goto Error } else { if filter.FilterEnabled() { go filter.MonitDiskUsage() } } netio = NewNetIOManager() netio.SetFilter(filter) proxy.epoll_fd, err = syscall.EpollCreate(proxy.max_listen_fds) if err != nil { logger.Critical("Failed to initialize epoll listener [%s].", err) goto Cleanup } netio.SetEpollFd(proxy.epoll_fd) err = netio.ProxyNetListen(&proxy.proxy_endpoint) if err != nil { logger.Critical("Failed to initialize server listener [%s].", err) goto Cleanup } setup_sighnd(proxy) logger.Info("Mongodb proxy server start.") for { wait_signal(proxy, syscall.SIGTERM) if proxy.quit { break } nfds, err := syscall.EpollWait(proxy.epoll_fd, proxy.events, proxy.timeout) if err != nil { logger.Critical("Failed to do epoll wait [%s].", err) break } for i := 0; i < nfds; i++ { fd := int(proxy.events[i].Fd) if netio.ProxyNetIsProxyServer(fd) { clientinfo, err := netio.ProxyNetAccept(&proxy.mongo_endpoint) if err != nil { logger.Critical("Failed to establish bridge between mongo client and server [%s].", err) } else { ipaddr, port := parse_sockaddr(clientinfo) logger.Debug("Succeed to establish bridge for client [%s:%d].", ipaddr, port) } } else { event := proxy.events[i].Events if event&syscall.EPOLLIN != 0 { errno := netio.ProxyNetRecv(fd) switch errno { case READ_ERROR: sa := netio.ProxyNetConnInfo(fd) if sa != nil { ipaddr, port := parse_sockaddr(sa) logger.Error("Failed to read data from [%s:%d].", ipaddr, port) } case SESSION_EOF: sa := netio.ProxyNetConnInfo(fd) if sa != nil { ipaddr, port := parse_sockaddr(sa) logger.Debug("One side [%s:%d] close the session.", ipaddr, port) } } if errno != NO_ERROR { netio.ProxyNetClosePeers(fd) } } if event&syscall.EPOLLOUT != 0 { errno := netio.ProxyNetSend(fd) switch errno { case WRITE_ERROR: sa := netio.ProxyNetConnInfo(fd) if sa != nil { ipaddr, port := parse_sockaddr(sa) logger.Error("Failed to write data to [%s:%d]", ipaddr, port) } case FILTER_BLOCK: sa := netio.ProxyNetConnInfo(fd) if sa != nil { ipaddr, port := parse_sockaddr(sa) logger.Error("Filter block request from client [%s:%d].", ipaddr, port) } } if errno != NO_ERROR { netio.ProxyNetClosePeers(fd) } } if event&syscall.EPOLLRDHUP != 0 { sa := netio.ProxyNetConnInfo(fd) if sa != nil { ipaddr, port := parse_sockaddr(sa) logger.Debug("shutdown connection with [%s:%d].", ipaddr, port) netio.ProxyNetClosePeers(fd) } } if event&syscall.EPOLLHUP != 0 { sa := netio.ProxyNetConnInfo(fd) if sa != nil { ipaddr, port := parse_sockaddr(sa) logger.Debug("shutdown connection with [%s:%d].", ipaddr, port) netio.ProxyNetClosePeers(fd) } } } } } Cleanup: netio.DestroyNetIO() Error: logger.Info("Mongodb proxy server quit.") logger.Close() return err }
func StartProxyServer(conf *ProxyConfig, proxy_log l4g.Logger) (err error) { logger = proxy_log var filter *IOFilterProtocol var netio *NetIOManager proxy := &ProxyServer{ max_listen_fds: 1024, timeout: 1000, quit: false, epoll_fd: -1, events: make([]syscall.EpollEvent, 100), sighnd: make(chan os.Signal, 1), } if !parse_config(proxy, conf) { logger.Error("Failed to initialize proxy server.") goto Error } filter = NewIOFilterProtocol(conf) if filter == nil { logger.Error("Failed to initialize filter protocol.") goto Error } else { if filter.FilterEnabled() { go filter.MonitQuotaFiles() go filter.MonitQuotaDataSize() } } netio = NewNetIOManager() netio.SetFilter(filter) proxy.epoll_fd, err = syscall.EpollCreate(proxy.max_listen_fds) if err != nil { logger.Critical("Failed to initialize epoll listener [%s].", err) goto Cleanup } netio.SetEpollFd(proxy.epoll_fd) err = netio.ProxyNetListen(&proxy.proxy_endpoint) if err != nil { logger.Critical("Failed to initialize server listener [%s].", err) goto Cleanup } setup_sighnd(proxy) logger.Info("Mongodb proxy server start.") for { wait_signal(proxy, syscall.SIGTERM) if proxy.quit { break } nfds, err := syscall.EpollWait(proxy.epoll_fd, proxy.events, proxy.timeout) if err != nil { logger.Critical("Failed to do epoll wait [%s].", err) break } for i := 0; i < nfds; i++ { fd := int(proxy.events[i].Fd) if netio.ProxyNetIsProxyServer(fd) { clientinfo, err := netio.ProxyNetAccept(&proxy.mongo_endpoint) if err != nil { logger.Critical("Failed to establish bridge between mongo client and server [%s].", err) } else { addr, port := parse_sockaddr(clientinfo) logger.Debug("Succeed to establish bridge for client [%s:%d].", addr, port) } } else { event := proxy.events[i].Events if event&syscall.EPOLLIN != 0 { errno := netio.ProxyNetRecv(fd) if errno != NO_ERROR { var addr string var port int sa := netio.ProxyNetConnInfo(fd) if sa != nil { addr, port = parse_sockaddr(sa) } switch errno { case READ_ERROR: if sa != nil { logger.Error("Failed to read data from [%s:%d].", addr, port) } case SESSION_EOF: /* normal close */ netio.ProxyNetFlush(fd) if sa != nil { logger.Debug("One side [%s:%d] close the session.", addr, port) } case UNKNOWN_ERROR: if sa != nil { logger.Debug("Unknown error during read happened at [%s:%d].", addr, port) } } netio.ProxyNetClosePeers(fd) } } if event&syscall.EPOLLOUT != 0 { errno := netio.ProxyNetSend(fd) if errno != NO_ERROR && errno != PARTIAL_SKB { var addr string var port int sa := netio.ProxyNetConnInfo(fd) if sa != nil { addr, port = parse_sockaddr(sa) } switch errno { case WRITE_ERROR: if sa != nil { logger.Error("Failed to write data to [%s:%d]", addr, port) } case FILTER_BLOCK: /* * 'block' handler only happens on 'proxy->server' io write, here * we need to log the 'client->proxy' connection information, if * we call 'ConnInfo' method we get the 'proxy->server' connection, * so we shall call 'OtherSideConnInfo' method here. */ sa = netio.ProxyNetOtherSideConnInfo(fd) if sa != nil { addr, port = parse_sockaddr(sa) logger.Error("Filter block request from client [%s:%d].", addr, port) } case UNKNOWN_ERROR: if sa != nil { logger.Debug("Unknown error during write happened at [%s:%d].", addr, port) } } netio.ProxyNetClosePeers(fd) } } if event&syscall.EPOLLRDHUP != 0 { netio.ProxyNetFlush(fd) sa := netio.ProxyNetConnInfo(fd) if sa != nil { ipaddr, port := parse_sockaddr(sa) logger.Debug("shutdown connection with [%s:%d].", ipaddr, port) netio.ProxyNetClosePeers(fd) } } if event&syscall.EPOLLHUP != 0 { netio.ProxyNetFlush(fd) sa := netio.ProxyNetConnInfo(fd) if sa != nil { ipaddr, port := parse_sockaddr(sa) logger.Debug("shutdown connection with [%s:%d].", ipaddr, port) netio.ProxyNetClosePeers(fd) } } } } } Cleanup: netio.DestroyNetIO() Error: logger.Info("Mongodb proxy server quit.") logger.Close() return err }
// Wait using epoll. // Returns true if something is ready to be read, // false if there is not. func (poller *fdPoller) wait() (bool, error) { // 3 possible events per fd, and 2 fds, makes a maximum of 6 events. // I don't know whether epoll_wait returns the number of events returned, // or the total number of events ready. // I decided to catch both by making the buffer one larger than the maximum. events := make([]syscall.EpollEvent, 7) for { n, errno := syscall.EpollWait(poller.epfd, events, -1) if n == -1 { if errno == syscall.EINTR { continue } return false, errno } if n == 0 { // If there are no events, try again. continue } if n > 6 { // This should never happen. More events were returned than should be possible. return false, errors.New("epoll_wait returned more events than I know what to do with") } ready := events[:n] epollhup := false epollerr := false epollin := false for _, event := range ready { if event.Fd == int32(poller.fd) { if event.Events&syscall.EPOLLHUP != 0 { // This should not happen, but if it does, treat it as a wakeup. epollhup = true } if event.Events&syscall.EPOLLERR != 0 { // If an error is waiting on the file descriptor, we should pretend // something is ready to read, and let syscall.Read pick up the error. epollerr = true } if event.Events&syscall.EPOLLIN != 0 { // There is data to read. epollin = true } } if event.Fd == int32(poller.pipe[0]) { if event.Events&syscall.EPOLLHUP != 0 { // Write pipe descriptor was closed, by us. This means we're closing down the // watcher, and we should wake up. } if event.Events&syscall.EPOLLERR != 0 { // If an error is waiting on the pipe file descriptor. // This is an absolute mystery, and should never ever happen. return false, errors.New("Error on the pipe descriptor.") } if event.Events&syscall.EPOLLIN != 0 { // This is a regular wakeup, so we have to clear the buffer. err := poller.clearWake() if err != nil { return false, err } } } } if epollhup || epollerr || epollin { return true, nil } return false, nil } }