Skip to content

Commit 017dcdd

Browse files
authored
Merge pull request #737 from JukLee0ira/fix-node
node, p2p/simulations: fix node.Node AccountsManager leak
2 parents fe801c8 + 6f9fb9d commit 017dcdd

File tree

12 files changed

+105
-15
lines changed

12 files changed

+105
-15
lines changed

cmd/XDC/chaincmd.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ func initGenesis(ctx *cli.Context) error {
203203

204204
// Open an initialise both full and light databases
205205
stack, _ := makeFullNode(ctx)
206+
defer stack.Close()
207+
206208
for _, name := range []string{"chaindata", "lightchaindata"} {
207209
chaindb, err := stack.OpenDatabase(name, 0, 0, "")
208210
if err != nil {
@@ -228,6 +230,8 @@ func importChain(ctx *cli.Context) error {
228230
go metrics.CollectProcessMetrics(3 * time.Second)
229231

230232
stack, _ := makeFullNode(ctx)
233+
defer stack.Close()
234+
231235
chain, chainDb := utils.MakeChain(ctx, stack)
232236
defer chainDb.Close()
233237

@@ -319,6 +323,8 @@ func exportChain(ctx *cli.Context) error {
319323
utils.Fatalf("This command requires an argument.")
320324
}
321325
stack, _ := makeFullNode(ctx)
326+
defer stack.Close()
327+
322328
chain, db := utils.MakeChain(ctx, stack)
323329
defer db.Close()
324330
start := time.Now()
@@ -353,6 +359,8 @@ func importPreimages(ctx *cli.Context) error {
353359
utils.Fatalf("This command requires an argument.")
354360
}
355361
stack, _ := makeFullNode(ctx)
362+
defer stack.Close()
363+
356364
diskdb := utils.MakeChainDatabase(ctx, stack)
357365
defer diskdb.Close()
358366

@@ -370,6 +378,8 @@ func exportPreimages(ctx *cli.Context) error {
370378
utils.Fatalf("This command requires an argument.")
371379
}
372380
stack, _ := makeFullNode(ctx)
381+
defer stack.Close()
382+
373383
diskdb := utils.MakeChainDatabase(ctx, stack)
374384
defer diskdb.Close()
375385

@@ -388,6 +398,8 @@ func copyDb(ctx *cli.Context) error {
388398
}
389399
// Initialize a new chain for the running node to sync into
390400
stack, _ := makeFullNode(ctx)
401+
defer stack.Close()
402+
391403
chain, chainDb := utils.MakeChain(ctx, stack)
392404
defer chainDb.Close()
393405

@@ -461,9 +473,11 @@ func removeDB(ctx *cli.Context) error {
461473

462474
func dump(ctx *cli.Context) error {
463475
stack, _ := makeFullNode(ctx)
476+
defer stack.Close()
477+
464478
chain, chainDb := utils.MakeChain(ctx, stack)
465479
defer chainDb.Close()
466-
480+
467481
for _, arg := range ctx.Args() {
468482
var block *types.Block
469483
if hashish(arg) {

cmd/XDC/consolecmd.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func localConsole(ctx *cli.Context) error {
7979
// Create and start the node based on the CLI flags
8080
node, cfg := makeFullNode(ctx)
8181
startNode(ctx, node, cfg)
82-
defer node.Stop()
82+
defer node.Close()
8383

8484
// Attach to the newly started node and start the JavaScript console
8585
client, err := node.Attach()
@@ -181,7 +181,7 @@ func ephemeralConsole(ctx *cli.Context) error {
181181
// Create and start the node based on the CLI flags
182182
node, cfg := makeFullNode(ctx)
183183
startNode(ctx, node, cfg)
184-
defer node.Stop()
184+
defer node.Close()
185185

186186
// Attach to the newly started node and start the JavaScript console
187187
client, err := node.Attach()

cmd/XDC/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ func main() {
226226
// blocking mode, waiting for it to be shut down.
227227
func XDC(ctx *cli.Context) error {
228228
node, cfg := makeFullNode(ctx)
229+
defer node.Close()
229230
startNode(ctx, node, cfg)
230231
node.Wait()
231232
return nil

cmd/faucet/faucet.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ func newFaucet(genesis *core.Genesis, port int, enodes []*discv5.Node, network u
287287

288288
// close terminates the Ethereum connection and tears down the faucet.
289289
func (f *faucet) close() error {
290-
return f.stack.Stop()
290+
return f.stack.Close()
291291
}
292292

293293
// listenAndServe registers the HTTP handlers for the faucet and boots it up

console/console_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,8 @@ func (env *tester) Close(t *testing.T) {
153153
if err := env.console.Stop(false); err != nil {
154154
t.Errorf("failed to stop embedded console: %v", err)
155155
}
156-
if err := env.stack.Stop(); err != nil {
157-
t.Errorf("failed to stop embedded node: %v", err)
156+
if err := env.stack.Close(); err != nil {
157+
t.Errorf("failed to tear down embedded node: %v", err)
158158
}
159159
os.RemoveAll(env.workspace)
160160
}

node/config_test.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,22 @@ func TestDatadirCreation(t *testing.T) {
3737
}
3838
defer os.RemoveAll(dir)
3939

40-
if _, err := New(&Config{DataDir: dir}); err != nil {
40+
node, err := New(&Config{DataDir: dir})
41+
if err != nil {
4142
t.Fatalf("failed to create stack with existing datadir: %v", err)
4243
}
44+
if err := node.Close(); err != nil {
45+
t.Fatalf("failed to close node: %v", err)
46+
}
4347
// Generate a long non-existing datadir path and check that it gets created by a node
4448
dir = filepath.Join(dir, "a", "b", "c", "d", "e", "f")
45-
if _, err := New(&Config{DataDir: dir}); err != nil {
49+
node, err = New(&Config{DataDir: dir})
50+
if err != nil {
4651
t.Fatalf("failed to create stack with creatable datadir: %v", err)
4752
}
53+
if err := node.Close(); err != nil {
54+
t.Fatalf("failed to close node: %v", err)
55+
}
4856
if _, err := os.Stat(dir); err != nil {
4957
t.Fatalf("freshly created datadir not accessible: %v", err)
5058
}
@@ -56,8 +64,12 @@ func TestDatadirCreation(t *testing.T) {
5664
defer os.Remove(file.Name())
5765

5866
dir = filepath.Join(file.Name(), "invalid/path")
59-
if _, err := New(&Config{DataDir: dir}); err == nil {
67+
node, err = New(&Config{DataDir: dir})
68+
if err == nil {
6069
t.Fatalf("protocol stack created with an invalid datadir")
70+
if err := node.Close(); err != nil {
71+
t.Fatalf("failed to close node: %v", err)
72+
}
6173
}
6274
}
6375

node/node.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,29 @@ func New(conf *Config) (*Node, error) {
131131
}, nil
132132
}
133133

134+
// Close stops the Node and releases resources acquired in
135+
// Node constructor New.
136+
func (n *Node) Close() error {
137+
var errs []error
138+
139+
// Terminate all subsystems and collect any errors
140+
if err := n.Stop(); err != nil && err != ErrNodeStopped {
141+
errs = append(errs, err)
142+
}
143+
if err := n.accman.Close(); err != nil {
144+
errs = append(errs, err)
145+
}
146+
// Report any errors that might have occurred
147+
switch len(errs) {
148+
case 0:
149+
return nil
150+
case 1:
151+
return errs[0]
152+
default:
153+
return fmt.Errorf("%v", errs)
154+
}
155+
}
156+
134157
// Register injects a new service into the node's stack. The service created by
135158
// the passed constructor must be unique in its type with regard to sibling ones.
136159
func (n *Node) Register(constructor ServiceConstructor) error {

node/node_example_test.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ import (
2929
// life cycle management.
3030
//
3131
// The following methods are needed to implement a node.Service:
32-
// - Protocols() []p2p.Protocol - devp2p protocols the service can communicate on
33-
// - APIs() []rpc.API - api methods the service wants to expose on rpc channels
34-
// - Start() error - method invoked when the node is ready to start the service
35-
// - Stop() error - method invoked when the node terminates the service
32+
// - Protocols() []p2p.Protocol - devp2p protocols the service can communicate on
33+
// - APIs() []rpc.API - api methods the service wants to expose on rpc channels
34+
// - Start() error - method invoked when the node is ready to start the service
35+
// - Stop() error - method invoked when the node terminates the service
3636
type SampleService struct{}
3737

3838
func (s *SampleService) Protocols() []p2p.Protocol { return nil }
@@ -47,6 +47,8 @@ func ExampleService() {
4747
if err != nil {
4848
log.Fatalf("Failed to create network node: %v", err)
4949
}
50+
defer stack.Close()
51+
5052
// Create and register a simple network service. This is done through the definition
5153
// of a node.ServiceConstructor that will instantiate a node.Service. The reason for
5254
// the factory method approach is to support service restarts without relying on the

node/node_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ func TestNodeLifeCycle(t *testing.T) {
4747
if err != nil {
4848
t.Fatalf("failed to create protocol stack: %v", err)
4949
}
50+
defer stack.Close()
51+
5052
// Ensure that a stopped node can be stopped again
5153
for i := 0; i < 3; i++ {
5254
if err := stack.Stop(); err != ErrNodeStopped {
@@ -89,6 +91,8 @@ func TestNodeUsedDataDir(t *testing.T) {
8991
if err != nil {
9092
t.Fatalf("failed to create original protocol stack: %v", err)
9193
}
94+
defer original.Close()
95+
9296
if err := original.Start(); err != nil {
9397
t.Fatalf("failed to start original protocol stack: %v", err)
9498
}
@@ -99,6 +103,8 @@ func TestNodeUsedDataDir(t *testing.T) {
99103
if err != nil {
100104
t.Fatalf("failed to create duplicate protocol stack: %v", err)
101105
}
106+
defer duplicate.Close()
107+
102108
if err := duplicate.Start(); err != ErrDatadirUsed {
103109
t.Fatalf("duplicate datadir failure mismatch: have %v, want %v", err, ErrDatadirUsed)
104110
}
@@ -110,6 +116,8 @@ func TestServiceRegistry(t *testing.T) {
110116
if err != nil {
111117
t.Fatalf("failed to create protocol stack: %v", err)
112118
}
119+
defer stack.Close()
120+
113121
// Register a batch of unique services and ensure they start successfully
114122
services := []ServiceConstructor{NewNoopServiceA, NewNoopServiceB, NewNoopServiceC}
115123
for i, constructor := range services {
@@ -142,6 +150,8 @@ func TestServiceLifeCycle(t *testing.T) {
142150
if err != nil {
143151
t.Fatalf("failed to create protocol stack: %v", err)
144152
}
153+
defer stack.Close()
154+
145155
// Register a batch of life-cycle instrumented services
146156
services := map[string]InstrumentingWrapper{
147157
"A": InstrumentedServiceMakerA,
@@ -192,6 +202,8 @@ func TestServiceRestarts(t *testing.T) {
192202
if err != nil {
193203
t.Fatalf("failed to create protocol stack: %v", err)
194204
}
205+
defer stack.Close()
206+
195207
// Define a service that does not support restarts
196208
var (
197209
running bool
@@ -240,6 +252,8 @@ func TestServiceConstructionAbortion(t *testing.T) {
240252
if err != nil {
241253
t.Fatalf("failed to create protocol stack: %v", err)
242254
}
255+
defer stack.Close()
256+
243257
// Define a batch of good services
244258
services := map[string]InstrumentingWrapper{
245259
"A": InstrumentedServiceMakerA,
@@ -287,6 +301,8 @@ func TestServiceStartupAbortion(t *testing.T) {
287301
if err != nil {
288302
t.Fatalf("failed to create protocol stack: %v", err)
289303
}
304+
defer stack.Close()
305+
290306
// Register a batch of good services
291307
services := map[string]InstrumentingWrapper{
292308
"A": InstrumentedServiceMakerA,
@@ -340,6 +356,8 @@ func TestServiceTerminationGuarantee(t *testing.T) {
340356
if err != nil {
341357
t.Fatalf("failed to create protocol stack: %v", err)
342358
}
359+
defer stack.Close()
360+
343361
// Register a batch of good services
344362
services := map[string]InstrumentingWrapper{
345363
"A": InstrumentedServiceMakerA,
@@ -415,6 +433,8 @@ func TestServiceRetrieval(t *testing.T) {
415433
if err != nil {
416434
t.Fatalf("failed to create protocol stack: %v", err)
417435
}
436+
defer stack.Close()
437+
418438
if err := stack.Register(NewNoopService); err != nil {
419439
t.Fatalf("noop service registration failed: %v", err)
420440
}
@@ -450,6 +470,8 @@ func TestProtocolGather(t *testing.T) {
450470
if err != nil {
451471
t.Fatalf("failed to create protocol stack: %v", err)
452472
}
473+
defer stack.Close()
474+
453475
// Register a batch of services with some configured number of protocols
454476
services := map[string]struct {
455477
Count int
@@ -506,6 +528,8 @@ func TestAPIGather(t *testing.T) {
506528
if err != nil {
507529
t.Fatalf("failed to create protocol stack: %v", err)
508530
}
531+
defer stack.Close()
532+
509533
// Register a batch of services with some configured APIs
510534
calls := make(chan string, 1)
511535
makeAPI := func(result string) *OneMethodAPI {

node/service_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ func TestContextServices(t *testing.T) {
6767
if err != nil {
6868
t.Fatalf("failed to create protocol stack: %v", err)
6969
}
70+
defer stack.Close()
7071
// Define a verifier that ensures a NoopA is before it and NoopB after
7172
verifier := func(ctx *ServiceContext) (Service, error) {
7273
var objA *NoopServiceA

0 commit comments

Comments
 (0)