Пример #1
0
func Listen(path string) (*Listener, error) {
	rname := ".ftrig-" + randomName()
	tmpfifo := filepath.Join(path, rname)
	err := syscall.Mkfifo(tmpfifo, syscall.S_IRUSR|syscall.S_IWUSR|syscall.S_IWGRP|syscall.S_IWOTH)
	if err != nil {
		return nil, err
	}

	fd, fdw, name := C.int(0), C.int(0), filepath.Join(path, rname[1:])
	fd, err = C.open_read(C.CString(tmpfifo))
	if fd == -1 {
		goto err1
	}

	fdw, err = C.open_write(C.CString(tmpfifo))
	if fd == -1 {
		C.fd_close(fd)
		goto err1
	}

	err = os.Rename(tmpfifo, name)
	if err != nil {
		C.fd_close(fdw)
		C.fd_close(fd)
		goto err1
	}

	err = syscall.SetNonblock(int(fd), false)
	if err != nil {
		goto err1
	}

	return subscribe(name, uintptr(fd), uintptr(fdw))
err1:
	os.Remove(tmpfifo)
	if errno, ok := err.(syscall.Errno); ok {
		return nil, errno
	}
	return nil, fmt.Errorf("unknown error opening fifo at %q", tmpfifo)
}
Пример #2
0
func notifyNosig(path, s string) (int, error) {
	files, err := ioutil.ReadDir(path)
	if err != nil {
		return 0, err
	}
	success := 0
	for i := range files {
		if files[i].Mode()&os.ModeNamedPipe == 0 {
			continue
		}
		p := filepath.Join(path, files[i].Name())
		fd, ferr := C.open_write(C.CString(p))
		if fd == -1 {
			if errno, ok := ferr.(syscall.Errno); ok && errno == syscall.ENXIO {
				err = errno
				os.Remove(p)
			}
		} else {
			r, ferr := C.fd_write(fd, C.CString(s), C.uint(len(s)))
			if (r < 0) || uint(r) < uint(len(s)) {
				if errno, ok := ferr.(syscall.Errno); ok && errno == syscall.EPIPE {
					err = errno
					os.Remove(p)
				}
				// what to do if EGAIN ? full fifo -> fix the reader !
				// There's a race condition in extreme cases though ;
				// but it's still better to be nonblocking - the writer
				// shouldn't get in trouble because of a bad reader.
				C.fd_close(fd)
			} else {
				C.fd_close(fd)
				success++
			}
		}
	}
	return success, err
}
Пример #3
0
func Clean(path string) error {
	files, err := ioutil.ReadDir(path)
	if err != nil {
		return nil // yes, we don't care if the dir failed to scan
	}
	for i := range files {
		if files[i].Mode()&os.ModeNamedPipe == 0 {
			continue
		}
		p := filepath.Join(path, files[i].Name())
		fd, ferr := C.open_write(C.CString(p))
		if fd >= 0 {
			C.fd_close(fd)
		} else if errno, ok := ferr.(syscall.Errno); ok && errno == syscall.ENXIO {
			err = os.Remove(p)
		}
	}
	return err
}
Пример #4
0
func (x *Listener) close() {
	os.Remove(x.path)
	C.fd_close(C.int(x.fdw))
	x.f.Close()
}