uapi: use kqueue for sock deletion on darwin
This commit is contained in:
		
							parent
							
								
									ac898bb35a
								
							
						
					
					
						commit
						e1de0f229a
					
				
					 2 changed files with 42 additions and 6 deletions
				
			
		
							
								
								
									
										4
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								main.go
									
									
									
									
									
								
							|  | @ -227,6 +227,10 @@ func main() { | ||||||
| 	term := make(chan os.Signal) | 	term := make(chan os.Signal) | ||||||
| 
 | 
 | ||||||
| 	uapi, err := UAPIListen(interfaceName, fileUAPI) | 	uapi, err := UAPIListen(interfaceName, fileUAPI) | ||||||
|  | 	if err != nil { | ||||||
|  | 		logger.Error.Println("Failed to listen on uapi socket:", err) | ||||||
|  | 		os.Exit(ExitSetupFailed) | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	go func() { | 	go func() { | ||||||
| 		for { | 		for { | ||||||
|  |  | ||||||
|  | @ -12,7 +12,6 @@ import ( | ||||||
| 	"net" | 	"net" | ||||||
| 	"os" | 	"os" | ||||||
| 	"path" | 	"path" | ||||||
| 	"time" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
|  | @ -28,6 +27,8 @@ type UAPIListener struct { | ||||||
| 	listener net.Listener // unix socket listener
 | 	listener net.Listener // unix socket listener
 | ||||||
| 	connNew  chan net.Conn | 	connNew  chan net.Conn | ||||||
| 	connErr  chan error | 	connErr  chan error | ||||||
|  | 	kqueueFd int | ||||||
|  | 	keventFd int | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (l *UAPIListener) Accept() (net.Conn, error) { | func (l *UAPIListener) Accept() (net.Conn, error) { | ||||||
|  | @ -43,7 +44,16 @@ func (l *UAPIListener) Accept() (net.Conn, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (l *UAPIListener) Close() error { | func (l *UAPIListener) Close() error { | ||||||
| 	return l.listener.Close() | 	err1 := unix.Close(l.kqueueFd) | ||||||
|  | 	err2 := unix.Close(l.keventFd) | ||||||
|  | 	err3 := l.listener.Close() | ||||||
|  | 	if err1 != nil { | ||||||
|  | 		return err1 | ||||||
|  | 	} | ||||||
|  | 	if err2 != nil { | ||||||
|  | 		return err2 | ||||||
|  | 	} | ||||||
|  | 	return err3 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (l *UAPIListener) Addr() net.Addr { | func (l *UAPIListener) Addr() net.Addr { | ||||||
|  | @ -65,8 +75,6 @@ func UAPIListen(name string, file *os.File) (net.Listener, error) { | ||||||
| 		connErr:  make(chan error, 1), | 		connErr:  make(chan error, 1), | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// watch for deletion of socket
 |  | ||||||
| 
 |  | ||||||
| 	socketPath := path.Join( | 	socketPath := path.Join( | ||||||
| 		socketDirectory, | 		socketDirectory, | ||||||
| 		fmt.Sprintf(socketName, name), | 		fmt.Sprintf(socketName, name), | ||||||
|  | @ -74,12 +82,36 @@ func UAPIListen(name string, file *os.File) (net.Listener, error) { | ||||||
| 
 | 
 | ||||||
| 	// watch for deletion of socket
 | 	// watch for deletion of socket
 | ||||||
| 
 | 
 | ||||||
|  | 	uapi.kqueueFd, err = unix.Kqueue() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	uapi.keventFd, err = unix.Open(socketDirectory, unix.O_EVTONLY, 0) | ||||||
|  | 	if err != nil { | ||||||
|  | 		unix.Close(uapi.kqueueFd) | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	go func(l *UAPIListener) { | 	go func(l *UAPIListener) { | ||||||
| 		for ; ; time.Sleep(time.Second) { | 		event := unix.Kevent_t{ | ||||||
| 			if _, err := os.Stat(socketPath); os.IsNotExist(err) { | 			Ident: uint64(uapi.keventFd), | ||||||
|  | 			Filter: unix.EVFILT_VNODE, | ||||||
|  | 			Flags: unix.EV_ADD | unix.EV_ENABLE | unix.EV_ONESHOT, | ||||||
|  | 			Fflags: unix.NOTE_WRITE, | ||||||
|  | 		} | ||||||
|  | 		events := make([]unix.Kevent_t, 1) | ||||||
|  | 		n := 1 | ||||||
|  | 		var kerr error | ||||||
|  | 		for { | ||||||
|  | 			// start with lstat to avoid race condition
 | ||||||
|  | 			if _, err := os.Lstat(socketPath); os.IsNotExist(err) { | ||||||
| 				l.connErr <- err | 				l.connErr <- err | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
|  | 			if kerr != nil || n != 1 { | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			n, kerr = unix.Kevent(uapi.kqueueFd, []unix.Kevent_t{event}, events, nil) | ||||||
| 		} | 		} | ||||||
| 	}(uapi) | 	}(uapi) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue