// 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]) }
// 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 }
func init() { fdM.Init(128) fd, err := syscall.EpollCreate1(syscall.EPOLL_CLOEXEC) if err != nil { log.Panicf("poller: EpollCreate1: %s", err.Error()) } epfd = fd go poller() }
func NewPerCpuEvents(config *PerfEventConfig) (*PerCpuEvents, error) { var err error e := &PerCpuEvents{ cpus: config.NumCpus, npages: config.NumPages, pagesize: os.Getpagesize(), event: make(map[int]*PerfEvent), } defer func() { if err != nil { e.CloseAll() } }() e.poll.fd, err = syscall.EpollCreate1(0) if err != nil { return nil, err } e.eventMap, err = openMap(config.MapPath) if err != nil { return nil, err } for cpu := int(0); cpu < config.NumCpus; cpu++ { event, err := PerfEventOpen(config, -1, cpu, -1, 0) if err != nil { return nil, err } else { e.event[event.Fd] = event } if err := e.poll.AddFD(event.Fd, syscall.EPOLLIN); err != nil { return nil, err } if err = event.Mmap(e.pagesize, e.npages); err != nil { return nil, err } if err = event.Enable(); err != nil { return nil, err } } for _, event := range e.event { // FIXME: Not sure what to do here, the map has already been updated and we can't // fully restore it. if err := e.eventMap.Update(event); err != nil { return nil, err } } return e, nil }
// NewIO allocates resources which will not be released before program // termination. You shouldn't need many instances. Panics on error. func NewIO() (io *IO) { epollFd, err := syscall.EpollCreate1(syscall.EPOLL_CLOEXEC) if err != nil { panic(err) } io = &IO{ epollFd: epollFd, workers: make(map[int32]*worker), } go io.eventLoop() return }
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 newpollster() (p *pollster, err error) { p = new(pollster) if p.epfd, err = syscall.EpollCreate1(syscall.EPOLL_CLOEXEC); err != nil { if err != syscall.ENOSYS { return nil, os.NewSyscallError("epoll_create1", err) } // The arg to epoll_create is a hint to the kernel // about the number of FDs we will care about. // We don't know, and since 2.6.8 the kernel ignores it anyhow. if p.epfd, err = syscall.EpollCreate(16); err != nil { return nil, os.NewSyscallError("epoll_create", err) } syscall.CloseOnExec(p.epfd) } p.events = make(map[int]uint32) return p, nil }
// 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 }
// 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 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 } }
// EpollCreate1 directly calls syscall.EpollCreate1 func EpollCreate1(flag int) (int, error) { return syscall.EpollCreate1(flag) }
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 (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 (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 (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") } }
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) } } } }