コード例 #1
0
ファイル: server.go プロジェクト: jedy/umgmt
func (server *UmgmtServer) Serve() error {
	relog.Info("started umgmt server: %v", server.listener.Addr())
	for {
		conn, err := server.listener.Accept()
		if err != nil {
			server.Lock()
			if server.quit {
				server.Unlock()
				return nil
			}
			server.Unlock()
			if err == syscall.EINVAL {
				return err
			}
			// syscall.EMFILE, syscall.ENFILE could happen here if you run out of file descriptors
			relog.Error("accept error %v", err)
			continue
		}

		server.Lock()
		server.connMap[conn] = true
		server.Unlock()

		rpc.ServeConn(conn)

		server.Lock()
		delete(server.connMap, conn)
		server.Unlock()
	}
	return nil
}
コード例 #2
0
ファイル: server.go プロジェクト: jedy/umgmt
func (service *UmgmtService) closeListeners() (err error) {
	service.mutex.Lock()
	defer service.mutex.Unlock()
	for _, l := range service.listeners {
		addr := l.Addr()
		closeErr := l.Close()
		if closeErr != nil {
			err := fmt.Errorf("failed to close listener on %v err:%v", addr, closeErr)
			// just return that at least one error happened, the log will reveal the rest
			relog.Error("%s", err)
		}
		relog.Info("closed listener %v", addr)
	}
	for _, f := range service.closeCallbacks {
		go f()
	}
	// Prevent duplicate execution.
	service.listeners = service.listeners[:0]
	return
}
コード例 #3
0
ファイル: server.go プロジェクト: jedy/umgmt
func ListenAndServe(addr string) error {
	rpc.Register(defaultService)
	server := &UmgmtServer{connMap: make(map[net.Conn]bool)}
	defer server.Close()

	var umgmtClient *Client

	for i := 2; i > 0; i-- {
		l, e := net.Listen("unix", addr)
		if e != nil {
			if umgmtClient != nil {
				umgmtClient.Close()
			}

			if checkError(e, syscall.EADDRINUSE) {
				var clientErr error
				umgmtClient, clientErr = Dial(addr)
				if clientErr == nil {
					closeErr := umgmtClient.CloseListeners()
					if closeErr != nil {
						relog.Error("closeErr:%v", closeErr)
					}
					// wait for rpc to finish
					rebindDelay := defaultService.rebindDelay()
					if rebindDelay > 0.0 {
						relog.Info("delaying rebind: %vs", rebindDelay)
						time.Sleep(rebindDelay)
					}
					continue
				} else if checkError(clientErr, syscall.ECONNREFUSED) {
					if unlinkErr := syscall.Unlink(addr); unlinkErr != nil {
						relog.Error("can't unlink %v err:%v", addr, unlinkErr)
					}
				} else {
					return e
				}
			} else {
				return e
			}
		} else {
			server.listener = l
			break
		}
	}
	if server.listener == nil {
		panic("unable to rebind umgmt socket")
	}
	// register the umgmt server itself for dropping - this seems like
	// the common case. i can't see when you *wouldn't* want to drop yourself
	defaultService.addListener(server)
	defaultService.addShutdownCallback(func() {
		server.handleGracefulShutdown()
	})

	// fire off the startup callbacks. if these bind ports, they should
	// call AddListener.
	for _, f := range defaultService.startupCallbacks {
		f()
	}

	if umgmtClient != nil {
		go func() {
			time.Sleep(defaultService.lameDuckPeriod())
			umgmtClient.GracefulShutdown()
			umgmtClient.Close()
		}()
	}
	err := server.Serve()
	// If we exitted gracefully, wait for the service to finish callbacks.
	if err == nil {
		<-defaultService.done
	}
	return err
}