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")
|
||||
jsonRPCRead(w, r, s)
|
||||
})
|
||||
|
||||
s.wg.Add(1)
|
||||
go s.walletListenerDuplicator()
|
||||
|
||||
rpcServeMux.HandleFunc("/wallet", func(w http.ResponseWriter, r *http.Request) {
|
||||
if err := s.checkAuth(r); err != nil {
|
||||
http.Error(w, "401 Unauthorized.", http.StatusUnauthorized)
|
||||
|
@ -203,9 +206,9 @@ func (s *rpcServer) Stop() error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
rpcsLog.Infof("RPC server shutdown complete")
|
||||
s.wg.Wait()
|
||||
close(s.quit)
|
||||
s.wg.Wait()
|
||||
rpcsLog.Infof("RPC server shutdown complete")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -367,7 +367,7 @@ func handleRescan(s *rpcServer, icmd btcjson.Cmd, c handlerChans) (interface{},
|
|||
// client requesting the rescan has disconnected.
|
||||
select {
|
||||
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())
|
||||
return nil, nil
|
||||
|
||||
|
@ -518,6 +518,7 @@ func (s *rpcServer) RemoveWalletListener(n ntfnChan) {
|
|||
func (s *rpcServer) walletListenerDuplicator() {
|
||||
// Duplicate all messages sent across walletNotificationMaster to each
|
||||
// listening wallet.
|
||||
out:
|
||||
for {
|
||||
select {
|
||||
case ntfn := <-s.ws.walletNotificationMaster:
|
||||
|
@ -528,9 +529,11 @@ func (s *rpcServer) walletListenerDuplicator() {
|
|||
s.ws.RUnlock()
|
||||
|
||||
case <-s.quit:
|
||||
return
|
||||
break out
|
||||
}
|
||||
}
|
||||
|
||||
s.wg.Done()
|
||||
}
|
||||
|
||||
// walletReqsNotifications is the handler function for websocket
|
||||
|
@ -587,7 +590,13 @@ func (s *rpcServer) walletReqsNotifications(ws *websocket.Conn) {
|
|||
case <-s.quit:
|
||||
// Server closed. Closing disconnected signals handlers to stop
|
||||
// and flushes all channels handlers may write to.
|
||||
close(disconnected)
|
||||
select {
|
||||
case <-disconnected:
|
||||
// nothing
|
||||
|
||||
default:
|
||||
close(disconnected)
|
||||
}
|
||||
|
||||
case <-disconnected:
|
||||
for {
|
||||
|
|
Loading…
Reference in a new issue