Fix several bugs in the RPC server shutdown.
The RPC server was performing some of the shutdown logic in the wrong order, that is, logging the the server has shut down, waiting for all server goroutines to finish, and then closing a channel to notify server goroutines to stop. These three items have been reversed to fix a hang where goroutines currently being waited on had not shut down because they did not receive the notification. While here, the server waitgroup was incremented for a goroutine that was running without it, another select statement was added to stop a duplicate close (which never occured last commit when I added the select statements), and the "stopping rescan" logging was moved to debug to make the ^C shutdown logging nicer.
This commit is contained in:
parent
d8227c2751
commit
bd98836a2b
2 changed files with 17 additions and 5 deletions
|
@ -147,7 +147,10 @@ func (s *rpcServer) Start() {
|
||||||
w.Header().Set("Connection", "close")
|
w.Header().Set("Connection", "close")
|
||||||
jsonRPCRead(w, r, s)
|
jsonRPCRead(w, r, s)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
s.wg.Add(1)
|
||||||
go s.walletListenerDuplicator()
|
go s.walletListenerDuplicator()
|
||||||
|
|
||||||
rpcServeMux.HandleFunc("/wallet", func(w http.ResponseWriter, r *http.Request) {
|
rpcServeMux.HandleFunc("/wallet", func(w http.ResponseWriter, r *http.Request) {
|
||||||
if err := s.checkAuth(r); err != nil {
|
if err := s.checkAuth(r); err != nil {
|
||||||
http.Error(w, "401 Unauthorized.", http.StatusUnauthorized)
|
http.Error(w, "401 Unauthorized.", http.StatusUnauthorized)
|
||||||
|
@ -203,9 +206,9 @@ func (s *rpcServer) Stop() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rpcsLog.Infof("RPC server shutdown complete")
|
|
||||||
s.wg.Wait()
|
|
||||||
close(s.quit)
|
close(s.quit)
|
||||||
|
s.wg.Wait()
|
||||||
|
rpcsLog.Infof("RPC server shutdown complete")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -367,7 +367,7 @@ func handleRescan(s *rpcServer, icmd btcjson.Cmd, c handlerChans) (interface{},
|
||||||
// client requesting the rescan has disconnected.
|
// client requesting the rescan has disconnected.
|
||||||
select {
|
select {
|
||||||
case <-c.disconnected:
|
case <-c.disconnected:
|
||||||
rpcsLog.Infof("Stopping rescan at height %v for disconnected client",
|
rpcsLog.Debugf("Stopping rescan at height %v for disconnected client",
|
||||||
blk.Height())
|
blk.Height())
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
||||||
|
@ -518,6 +518,7 @@ func (s *rpcServer) RemoveWalletListener(n ntfnChan) {
|
||||||
func (s *rpcServer) walletListenerDuplicator() {
|
func (s *rpcServer) walletListenerDuplicator() {
|
||||||
// Duplicate all messages sent across walletNotificationMaster to each
|
// Duplicate all messages sent across walletNotificationMaster to each
|
||||||
// listening wallet.
|
// listening wallet.
|
||||||
|
out:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case ntfn := <-s.ws.walletNotificationMaster:
|
case ntfn := <-s.ws.walletNotificationMaster:
|
||||||
|
@ -528,9 +529,11 @@ func (s *rpcServer) walletListenerDuplicator() {
|
||||||
s.ws.RUnlock()
|
s.ws.RUnlock()
|
||||||
|
|
||||||
case <-s.quit:
|
case <-s.quit:
|
||||||
return
|
break out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.wg.Done()
|
||||||
}
|
}
|
||||||
|
|
||||||
// walletReqsNotifications is the handler function for websocket
|
// walletReqsNotifications is the handler function for websocket
|
||||||
|
@ -587,7 +590,13 @@ func (s *rpcServer) walletReqsNotifications(ws *websocket.Conn) {
|
||||||
case <-s.quit:
|
case <-s.quit:
|
||||||
// Server closed. Closing disconnected signals handlers to stop
|
// Server closed. Closing disconnected signals handlers to stop
|
||||||
// and flushes all channels handlers may write to.
|
// and flushes all channels handlers may write to.
|
||||||
close(disconnected)
|
select {
|
||||||
|
case <-disconnected:
|
||||||
|
// nothing
|
||||||
|
|
||||||
|
default:
|
||||||
|
close(disconnected)
|
||||||
|
}
|
||||||
|
|
||||||
case <-disconnected:
|
case <-disconnected:
|
||||||
for {
|
for {
|
||||||
|
|
Loading…
Reference in a new issue