예제 #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])
}
예제 #2
0
func (p *pollster) StopWaiting(fd int, bits uint) {
	events, already := p.events[fd]
	if !already {
		print("Epoll unexpected fd=", fd, "\n")
		return
	}

	// If syscall.EPOLLONESHOT is not set, the wait
	// is a repeating wait, so don't change it.
	if events&syscall.EPOLLONESHOT == 0 {
		return
	}

	// Disable the given bits.
	// If we're still waiting for other events, modify the fd
	// event in the kernel.  Otherwise, delete it.
	events &= ^uint32(bits)
	if int32(events)&^syscall.EPOLLONESHOT != 0 {
		var ev syscall.EpollEvent
		ev.Fd = int32(fd)
		ev.Events = events
		if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &ev); e != 0 {
			print("Epoll modify fd=", fd, ": ", os.Errno(e).String(), "\n")
		}
		p.events[fd] = events
	} else {
		if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != 0 {
			print("Epoll delete fd=", fd, ": ", os.Errno(e).String(), "\n")
		}
		p.events[fd] = 0, false
	}
}
예제 #3
0
func (p *pollster) StopWaiting(fd int, bits uint) {
	// pollServer is locked.

	events, already := p.events[fd]
	if !already {
		// The fd returned by the kernel may have been
		// cancelled already; return silently.
		return
	}

	// If syscall.EPOLLONESHOT is not set, the wait
	// is a repeating wait, so don't change it.
	if events&syscall.EPOLLONESHOT == 0 {
		return
	}

	// Disable the given bits.
	// If we're still waiting for other events, modify the fd
	// event in the kernel.  Otherwise, delete it.
	events &= ^uint32(bits)
	if int32(events)&^syscall.EPOLLONESHOT != 0 {
		p.ctlEvent.Fd = int32(fd)
		p.ctlEvent.Events = events
		if err := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &p.ctlEvent); err != nil {
			print("Epoll modify fd=", fd, ": ", err.Error(), "\n")
		}
		p.events[fd] = events
	} else {
		if err := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); err != nil {
			print("Epoll delete fd=", fd, ": ", err.Error(), "\n")
		}
		delete(p.events, fd)
	}
}
예제 #4
0
func (io *NetIOManager) ProxyNetAccept(serverinfo syscall.Sockaddr) (sa syscall.Sockaddr, err error) {
	var clientfd, serverfd int
	// accpet mongodb client connection request
	clientfd, clientinfo, err := syscall.Accept(io.proxy_server_fd)
	if err != nil {
		goto ClientError
	}

	err = syscall.SetNonblock(clientfd, true)
	if err != nil {
		goto ClientCleanup
	}

	err = syscall.EpollCtl(io.epoll_fd, syscall.EPOLL_CTL_ADD, clientfd,
		&syscall.EpollEvent{Events: syscall.EPOLLIN | syscall.EPOLLOUT |
			syscall.EPOLLRDHUP, Fd: int32(clientfd)})
	if err != nil {
		goto ClientCleanup
	}

	// establish connection with mongodb server
	serverfd, err = syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM,
		syscall.IPPROTO_TCP)
	if err != nil {
		goto ServerError
	}

	err = syscall.Connect(serverfd, serverinfo)
	if err != nil {
		goto ServerCleanup
	}

	err = syscall.SetNonblock(serverfd, true)
	if err != nil {
		goto ServerCleanup
	}

	err = syscall.EpollCtl(io.epoll_fd, syscall.EPOLL_CTL_ADD, serverfd,
		&syscall.EpollEvent{Events: syscall.EPOLLIN | syscall.EPOLLOUT |
			syscall.EPOLLRDHUP, Fd: int32(serverfd)})
	if err != nil {
		goto ServerCleanup
	}

	// now proxy server becomes a bridge between client <-> server
	add_sock_peer(io, clientfd, clientinfo, serverfd, serverinfo)
	return clientinfo, nil

ServerCleanup:
	syscall.Close(serverfd)
ServerError:
	syscall.EpollCtl(io.epoll_fd, syscall.EPOLL_CTL_DEL, clientfd,
		&syscall.EpollEvent{Events: syscall.EPOLLIN | syscall.EPOLLOUT |
			syscall.EPOLLRDHUP, Fd: int32(clientfd)})
ClientCleanup:
	syscall.Close(clientfd)
ClientError:
	return nil, err
}
예제 #5
0
func (fd *FD) closeUnlocked() error {
	// Caller MUST already hold the C lock. Take the both R and W
	// locks, to exclude Read and Write operations from accessing
	// a closed sysfd.
	fd.r.cond.L.Lock()
	fd.w.cond.L.Lock()

	fd.closed = true
	// ev is not used by EpollCtl/DEL. Just don't pass a nil
	// pointer.
	var ev syscall.EpollEvent
	err := syscall.EpollCtl(epfd, syscall.EPOLL_CTL_DEL, fd.sysfd, &ev)
	if err != nil {
		log.Printf("poller: EpollCtl/DEL (fd=%d, sysfd=%d): %s",
			fd.id, fd.sysfd, err.Error())
	}
	if fd.r.timer != nil {
		fd.r.timer.Stop()
	}
	if fd.w.timer != nil {
		fd.w.timer.Stop()
	}
	fdM.DelFD(fd.id)
	err = syscall.Close(fd.sysfd)

	// Wake up everybody waiting on the FD.
	fd.r.cond.Broadcast()
	fd.w.cond.Broadcast()

	debugf("FD %03d: CL: close(sysfd=%d)", fd.id, fd.sysfd)

	fd.w.cond.L.Unlock()
	fd.r.cond.L.Unlock()
	return err
}
예제 #6
0
func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
	// pollServer is locked.

	var already bool
	p.ctlEvent.Fd = int32(fd)
	p.ctlEvent.Events, already = p.events[fd]
	if !repeat {
		p.ctlEvent.Events |= syscall.EPOLLONESHOT
	}
	if mode == 'r' {
		p.ctlEvent.Events |= readFlags
	} else {
		p.ctlEvent.Events |= writeFlags
	}

	var op int
	if already {
		op = syscall.EPOLL_CTL_MOD
	} else {
		op = syscall.EPOLL_CTL_ADD
	}
	if e := syscall.EpollCtl(p.epfd, op, fd, &p.ctlEvent); e != nil {
		return false, os.NewSyscallError("epoll_ctl", e)
	}
	p.events[fd] = p.ctlEvent.Events
	return false, nil
}
예제 #7
0
func (p *pollster) AddFD(fd int, mode int, repeat bool) os.Error {
	var ev syscall.EpollEvent
	var already bool
	ev.Fd = int32(fd)
	ev.Events, already = p.events[fd]
	if !repeat {
		ev.Events |= syscall.EPOLLONESHOT
	}
	if mode == 'r' {
		ev.Events |= readFlags
	} else {
		ev.Events |= writeFlags
	}

	var op int
	if already {
		op = syscall.EPOLL_CTL_MOD
	} else {
		op = syscall.EPOLL_CTL_ADD
	}
	if e := syscall.EpollCtl(p.epfd, op, fd, &ev); e != 0 {
		return os.NewSyscallError("epoll_ctl", e)
	}
	p.events[fd] = ev.Events
	return nil
}
예제 #8
0
func (io *NetIOManager) ProxyNetListen(sa syscall.Sockaddr) error {
	serverfd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM,
		syscall.IPPROTO_TCP)
	if err != nil {
		goto Error
	}

	err = syscall.Bind(serverfd, sa)
	if err != nil {
		goto Cleanup
	}

	err = syscall.Listen(serverfd, io.max_backlog)
	if err != nil {
		goto Cleanup
	}

	err = syscall.EpollCtl(io.epoll_fd, syscall.EPOLL_CTL_ADD, serverfd,
		&syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(serverfd)})
	if err != nil {
		goto Cleanup
	}

	io.proxy_server_fd = serverfd
	return nil

Cleanup:
	syscall.Close(serverfd)
Error:
	return err
}
예제 #9
0
func registerInterrupt(pin *digitalPin, handler func(embd.DigitalPin)) error {
	l := getEpollListenerInstance()

	pinFd := int(pin.val.Fd())

	l.mu.Lock()
	defer l.mu.Unlock()

	if _, ok := l.interruptablePins[pinFd]; ok {
		return ErrorPinAlreadyRegistered
	}

	var event syscall.EpollEvent
	event.Events = syscall.EPOLLIN | (syscall.EPOLLET & 0xffffffff) | syscall.EPOLLPRI

	if err := syscall.SetNonblock(pinFd, true); err != nil {
		return err
	}

	event.Fd = int32(pinFd)

	if err := syscall.EpollCtl(l.fd, syscall.EPOLL_CTL_ADD, pinFd, &event); err != nil {
		return err
	}

	l.interruptablePins[pinFd] = &interrupt{pin: pin, handler: handler}

	return nil
}
예제 #10
0
func newFD(sysfd int) (*FD, error) {
	// Set sysfd to non-blocking mode
	err := syscall.SetNonblock(sysfd, true)
	if err != nil {
		debugf("FD xxx: NF: sysfd=%d, err=%v", sysfd, err)
		return nil, err
	}
	// Initialize FD
	fd := &FD{sysfd: sysfd}
	fd.id = fdM.GetID()
	fd.r.cond = sync.NewCond(&fd.r.mu)
	fd.w.cond = sync.NewCond(&fd.w.mu)
	// Add to Epoll set. We may imediatelly start receiving events
	// after this. They will be dropped since the FD is not yet in
	// fdMap. It's ok. Nobody is waiting on this FD yet, anyway.
	ev := syscall.EpollEvent{
		Events: syscall.EPOLLIN |
			syscall.EPOLLOUT |
			syscall.EPOLLRDHUP |
			(syscall.EPOLLET & 0xffffffff),
		Fd: int32(fd.id)}
	err = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd.sysfd, &ev)
	if err != nil {
		debugf("FD %03d: NF: sysfd=%d, err=%v", fd.id, fd.sysfd, err)
		return nil, err
	}
	// Add to fdMap
	fdM.AddFD(fd)
	debugf("FD %03d: NF: sysfd=%d", fd.id, fd.sysfd)
	return fd, nil
}
예제 #11
0
파일: gpio_linux.go 프로젝트: hagna/gpio
func (p *pin) BeginWatch(edge Edge, callback IRQEvent) error {
	p.SetMode(ModeInput)
	if err := write([]byte(edge), p.edgePath); err != nil {
		return err
	}

	var event syscall.EpollEvent
	event.Events = syscall.EPOLLIN | (syscall.EPOLLET & 0xffffffff) | syscall.EPOLLPRI

	fd := int(p.valueFile.Fd())

	p.callback = callback
	watchEventCallbacks[fd] = p

	if err := syscall.SetNonblock(fd, true); err != nil {
		return err
	}

	event.Fd = int32(fd)

	if err := syscall.EpollCtl(epollFD, syscall.EPOLL_CTL_ADD, fd, &event); err != nil {
		return err
	}

	return nil

}
예제 #12
0
파일: gpio.go 프로젝트: voxadam/go-embedded
func (gpio *GPIO) DisableEdgeDetection() {
	epollFd := gpio.epollFd.Swap(0)
	if epollFd != 0 {
		syscall.EpollCtl(epollFd, syscall.EPOLL_CTL_DEL, int(gpio.valueFile.Fd()), new(syscall.EpollEvent))
		syscall.Close(epollFd)
	}
	gpio.setEdge(EDGE_NONE)
}
예제 #13
0
func sock_close(io *NetIOManager, fd int) {
	syscall.EpollCtl(io.epoll_fd, syscall.EPOLL_CTL_DEL, fd,
		&syscall.EpollEvent{Events: syscall.EPOLLIN | syscall.EPOLLOUT |
			syscall.EPOLLRDHUP, Fd: int32(fd)})
	syscall.Close(fd)
	delete(io.pending_output_skbs, fd)
	delete(io.io_socket_peers, fd)
}
예제 #14
0
파일: perf.go 프로젝트: cilium-team/cilium
func (ep *EPoll) AddFD(fd int, events uint32) error {
	ev := syscall.EpollEvent{
		Events: events,
		Fd:     int32(fd),
	}

	return syscall.EpollCtl(ep.fd, syscall.EPOLL_CTL_ADD, fd, &ev)
}
예제 #15
0
파일: io.go 프로젝트: ninchat/zmq4chan
// Add registers a socket for sending and/or receiving.  The caller can't
// access the socket directly after this.  The send channel (if any) should be
// closed by the caller.
func (io *IO) Add(s *zmq.Socket, send <-chan Data, recv chan<- Data) (err error) {
	fd, err := s.GetFd()
	if err != nil {
		return
	}

	w := newWorker()

	io.lock.Lock()
	io.workers[int32(fd)] = w
	io.lock.Unlock()

	defer func() {
		if err != nil {
			io.lock.Lock()
			delete(io.workers, int32(fd))
			io.lock.Unlock()
		}
	}()

	e := &syscall.EpollEvent{
		Events: syscall.EPOLLIN | syscall.EPOLLET&0xffffffff,
		Fd:     int32(fd),
	}

	if err = syscall.EpollCtl(io.epollFd, syscall.EPOLL_CTL_ADD, fd, e); err != nil {
		return
	}

	state, err := s.GetEvents()
	if err != nil {
		syscall.EpollCtl(io.epollFd, syscall.EPOLL_CTL_DEL, fd, nil)
		return
	}

	go func() {
		defer s.Close()
		defer syscall.EpollCtl(io.epollFd, syscall.EPOLL_CTL_DEL, fd, nil)

		w.socketLoop(s, send, recv, state)
	}()

	return
}
예제 #16
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
}
예제 #17
0
파일: gpio.go 프로젝트: ungerik/go-bbio
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
}
예제 #18
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
}
예제 #19
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
}
예제 #20
0
func (m *Monitor) start() {
	var events [128]syscall.EpollEvent
	for {
		n, err := archutils.EpollWait(m.epollFd, events[:], -1)
		if err != nil {
			if err == syscall.EINTR {
				continue
			}
			logrus.WithField("error", err).Fatal("containerd: epoll wait")
		}
		// process events
		for i := 0; i < n; i++ {
			fd := int(events[i].Fd)
			m.m.Lock()
			r := m.receivers[fd]
			switch t := r.(type) {
			case runtime.Process:
				if events[i].Events == syscall.EPOLLHUP {
					delete(m.receivers, fd)
					if err = syscall.EpollCtl(m.epollFd, syscall.EPOLL_CTL_DEL, fd, &syscall.EpollEvent{
						Events: syscall.EPOLLHUP,
						Fd:     int32(fd),
					}); err != nil {
						logrus.WithField("error", err).Error("containerd: epoll remove fd")
					}
					if err := t.Close(); err != nil {
						logrus.WithField("error", err).Error("containerd: close process IO")
					}
					EpollFdCounter.Dec(1)
					m.exits <- t
				}
			case runtime.OOM:
				// always flush the event fd
				t.Flush()
				if t.Removed() {
					delete(m.receivers, fd)
					// epoll will remove the fd from its set after it has been closed
					t.Close()
					EpollFdCounter.Dec(1)
				} else {
					m.ooms <- t.ContainerID()
				}
			}
			m.m.Unlock()
		}
	}
}
예제 #21
0
파일: gpio_linux.go 프로젝트: hagna/gpio
// EndWatch stops watching the pin
func (p *pin) EndWatch() error {

	fd := int(p.valueFile.Fd())

	if err := syscall.EpollCtl(epollFD, syscall.EPOLL_CTL_DEL, fd, nil); err != nil {
		return err
	}

	if err := syscall.SetNonblock(fd, false); err != nil {
		return err
	}

	delete(watchEventCallbacks, fd)

	return nil

}
예제 #22
0
파일: gpio.go 프로젝트: voxadam/go-embedded
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()
}
예제 #23
0
파일: inotify_unix.go 프로젝트: udhos/tabby
func init_inotify() {
	var err error

	name_by_wd = make(map[int32]string)
	wd_by_name = make(map[string]int32)
	var event syscall.InotifyEvent
	event_size = int(unsafe.Sizeof(event))
	inotify_fd, _ = syscall.InotifyInit()
	if -1 == inotify_fd {
		bump_message("InotifyInit failed, file changes outside of tabby " +
			"will remain unnoticed")
		return
	}
	epoll_fd, err = syscall.EpollCreate(1)
	if -1 == epoll_fd {
		tabby_log("init_inotify: " + err.Error())
	}
	var epoll_event syscall.EpollEvent
	epoll_event.Events = syscall.EPOLLIN
	syscall.EpollCtl(epoll_fd, syscall.EPOLL_CTL_ADD, inotify_fd, &epoll_event)
	go inotify_observe()
}
예제 #24
0
func unregisterInterrupt(pin *digitalPin) error {
	l := getEpollListenerInstance()

	pinFd := int(pin.val.Fd())

	l.mu.Lock()
	defer l.mu.Unlock()

	if _, ok := l.interruptablePins[pinFd]; !ok {
		return nil
	}

	if err := syscall.EpollCtl(l.fd, syscall.EPOLL_CTL_DEL, pinFd, nil); err != nil {
		return err
	}

	if err := syscall.SetNonblock(pinFd, false); err != nil {
		return err
	}

	delete(l.interruptablePins, pinFd)
	return nil
}
예제 #25
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")
		}
	}
}
예제 #26
0
파일: netlink.go 프로젝트: lebauce/skydive
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))
			}
		}
	}
}
예제 #27
0
파일: parent.go 프로젝트: rhenium/poe
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
}
예제 #28
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
	}
}
예제 #29
0
			return err
		}},
	{
		ErrFmt: "Bind epoll fd error [%s]\n",
		Action: func(t *Tunnel) error {
			return syscall.Bind(t.LFd, &syscall.SockaddrInet4{Port: int(t.EPort), Addr: [4]byte{0, 0, 0, 0}})
		}},
	{
		ErrFmt: "Listen fd error [%s]\n",
		Action: func(t *Tunnel) error {
			return syscall.Listen(t.LFd, 10)
		}},
	{
		ErrFmt: "Add fd to epoll error [%s]\n",
		Action: func(t *Tunnel) error {
			return syscall.EpollCtl(epollFd, syscall.EPOLL_CTL_ADD, t.LFd, &syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(t.LFd)})
		}},
}

var pathAddStep = [...]TunnelStep{
	{
		ErrFmt: "Port [%d] accept error [%s]",
		Action: func(tc *TunnelConn) (err error) {
			tc.EFd, _, err = syscall.Accept(tc.RelTunnel.LFd)
			return
		}},
	{
		ErrFmt: "Port [%d] set fd nonblock error [%s]",
		Action: func(tc *TunnelConn) (err error) {
			return syscall.SetNonblock(tc.EFd, true)
		}},
예제 #30
0
// EpollCtl directly calls syscall.EpollCtl
func EpollCtl(epfd int, op int, fd int, event *syscall.EpollEvent) error {
	return syscall.EpollCtl(epfd, op, fd, event)
}