Ejemplo n.º 1
1
// 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])
}
Ejemplo n.º 2
0
// 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)])
				}
			}
		}
	}
}
Ejemplo n.º 4
0
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
}
Ejemplo n.º 5
0
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()
}
Ejemplo n.º 6
0
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
}
Ejemplo n.º 7
0
// 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
}
Ejemplo n.º 8
0
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
}
Ejemplo n.º 9
0
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
}
Ejemplo n.º 10
0
// 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
}
Ejemplo n.º 11
0
// 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
}
Ejemplo n.º 12
0
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")
		}
	}
}
Ejemplo n.º 13
0
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))
			}
		}
	}
}
Ejemplo n.º 14
0
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
}
Ejemplo n.º 15
0
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
	}
}
Ejemplo n.º 16
0
// EpollCreate1 directly calls syscall.EpollCreate1
func EpollCreate1(flag int) (int, error) {
	return syscall.EpollCreate1(flag)
}
Ejemplo n.º 17
0
Archivo: linux.go Proyecto: hkwi/fdset
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
}
Ejemplo n.º 18
0
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()
}
Ejemplo n.º 19
0
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()
}
Ejemplo n.º 20
0
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")
	}
}
Ejemplo n.º 21
0
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)
			}
		}
	}
}