cli/node: Fix deadlock produced by instant RPC service start
If `StartWhenSynchronized` is unset in config, `node` command runs RPC service instantly. Previously there was a ground for deadlock. Command started RPC server synchronously. According to server implementation, it sends all internal failures to the parameterized error channel. Deadlock occured because main routine didn't scan the channel. Run `rpcsrv.Server.Start` in a separate go-routine in `startServer`. This prevents potential deadlock caused by writing into unread channel. Fixes #2896. Signed-off-by: Leonard Lyubich <leonard@morphbits.io>
This commit is contained in:
parent
465d3f43d2
commit
6e990f39de
1 changed files with 6 additions and 2 deletions
|
@ -491,7 +491,10 @@ func startServer(ctx *cli.Context) error {
|
||||||
|
|
||||||
go serv.Start()
|
go serv.Start()
|
||||||
if !cfg.ApplicationConfiguration.RPC.StartWhenSynchronized {
|
if !cfg.ApplicationConfiguration.RPC.StartWhenSynchronized {
|
||||||
rpcServer.Start()
|
// Run RPC server in a separate routine. This is necessary to avoid a potential
|
||||||
|
// deadlock: Start() can write errors to errChan which is not yet read in the
|
||||||
|
// current execution context (see for-loop below).
|
||||||
|
go rpcServer.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
sigCh := make(chan os.Signal, 1)
|
sigCh := make(chan os.Signal, 1)
|
||||||
|
@ -546,7 +549,8 @@ Main:
|
||||||
rpcServer = rpcsrv.New(chain, cfgnew.ApplicationConfiguration.RPC, serv, oracleSrv, log, errChan)
|
rpcServer = rpcsrv.New(chain, cfgnew.ApplicationConfiguration.RPC, serv, oracleSrv, log, errChan)
|
||||||
serv.AddService(&rpcServer)
|
serv.AddService(&rpcServer)
|
||||||
if !cfgnew.ApplicationConfiguration.RPC.StartWhenSynchronized || serv.IsInSync() {
|
if !cfgnew.ApplicationConfiguration.RPC.StartWhenSynchronized || serv.IsInSync() {
|
||||||
rpcServer.Start()
|
// Here similar to the initial run (see above for-loop), so async.
|
||||||
|
go rpcServer.Start()
|
||||||
}
|
}
|
||||||
pprof.ShutDown()
|
pprof.ShutDown()
|
||||||
pprof = metrics.NewPprofService(cfgnew.ApplicationConfiguration.Pprof, log)
|
pprof = metrics.NewPprofService(cfgnew.ApplicationConfiguration.Pprof, log)
|
||||||
|
|
Loading…
Reference in a new issue