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 }
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 }
func SigTermHandler(signal os.Signal) { relog.Info("SigTermHandler") defaultService.closeListeners() time.Sleep(defaultService.lameDuckPeriod()) defaultService.gracefulShutdown() }
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 }
func (service *UmgmtService) Ping(request *Request, reply *Reply) error { relog.Info("ping") reply.Message = "pong" return nil }