fix: make start node test friendly and fix several memory leak#198
fix: make start node test friendly and fix several memory leak#198g11tech merged 9 commits intoblockblaz:mainfrom
Conversation
Signed-off-by: Chen Kai <[email protected]>
There was a problem hiding this comment.
Pull Request Overview
This PR refactors the node architecture to make it more testing-friendly by introducing a proper Node struct that encapsulates all components and provides explicit lifecycle management. The changes also address memory leaks by adding deinit methods throughout the codebase.
- Transforms the standalone
startNodefunction into aNodestruct with clear initialization and cleanup methods - Adds comprehensive deinit methods to prevent memory leaks across multiple components
- Improves ownership management for allocated resources like network addresses and callback wrappers
Reviewed Changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| pkgs/types/src/lib.zig | Adds deinit method to BeamState for cleaning up allocated slices |
| pkgs/node/src/node.zig | Adds deinit method to BeamNode for proper chain cleanup |
| pkgs/node/src/clock.zig | Adds deinit method to Clock for timer and callback cleanup |
| pkgs/node/src/chain.zig | Adds deinit method to BeamChain for states HashMap cleanup |
| pkgs/network/src/ethlibp2p.zig | Adds deinit method to EthLibp2p for address cleanup |
| pkgs/cli/src/node.zig | Major refactor introducing Node struct and moving ownership management |
| pkgs/cli/src/metrics_server.riz | Adds cleanup for metrics server allocation |
| pkgs/cli/src/main.zig | Updates to use new Node struct API |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
pkgs/cli/src/node.zig
Outdated
|
|
||
| var node_multiaddrs = try self.enr.multiaddrP2PQUIC(allocator); | ||
| defer node_multiaddrs.deinit(allocator); | ||
| // move the ownership to the `EthLibp2p`, will be freed in its deinit |
There was a problem hiding this comment.
[nitpick] These comments about ownership transfer are helpful but could be more specific about what happens if the EthLibp2p initialization fails after ownership transfer. Consider documenting the cleanup responsibility in case of initialization failure.
| // move the ownership to the `EthLibp2p`, will be freed in its deinit | |
| // Ownership of `listen_addresses` is transferred to `EthLibp2p` and will be freed in its deinit. | |
| // If EthLibp2p initialization fails after this point, the caller is responsible for freeing | |
| // `listen_addresses` to avoid a memory leak. |
pkgs/cli/src/node.zig
Outdated
| } | ||
| } | ||
|
|
||
| // move the ownership to the `EthLibp2p`, will be freed in its deinit |
There was a problem hiding this comment.
[nitpick] These comments about ownership transfer are helpful but could be more specific about what happens if the EthLibp2p initialization fails after ownership transfer. Consider documenting the cleanup responsibility in case of initialization failure.
| // move the ownership to the `EthLibp2p`, will be freed in its deinit | |
| // Ownership of `connect_peers` is transferred to `EthLibp2p` and will be freed in its deinit. | |
| // If `EthLibp2p` initialization fails after this point, the caller is responsible for freeing `connect_peers`. |
pkgs/cli/src/node.zig
Outdated
|
|
||
| self.clock = try Clock.init(allocator, chain_config.genesis.genesis_time, &self.loop); | ||
|
|
||
| const beam_node = try BeamNode.init(allocator, .{ |
There was a problem hiding this comment.
[nitpick] The variable beam_node is only used to assign to self.beam_node. Consider directly assigning the result of BeamNode.init to self.beam_node to eliminate the intermediate variable.
pkgs/cli/src/node.zig
Outdated
| .logger = options.logger, | ||
| }); | ||
|
|
||
| self.beam_node = beam_node; |
There was a problem hiding this comment.
[nitpick] The variable beam_node is only used to assign to self.beam_node. Consider directly assigning the result of BeamNode.init to self.beam_node to eliminate the intermediate variable.
| port: u16, | ||
|
|
||
| fn run(self: *SimpleMetricsServer) !void { | ||
| // `startMetricsServer` creates this, so we need to free it here |
There was a problem hiding this comment.
[nitpick] The comment references startMetricsServer but this function name is not visible in the current diff context. Consider making the comment more explicit about where this allocation occurs or use a more generic description.
| // `startMetricsServer` creates this, so we need to free it here | |
| // This struct was heap-allocated and must be freed here to avoid memory leaks |
Co-authored-by: Copilot <[email protected]>
| // historical_block_hashes and justified_slots are slices so need to be freed | ||
| // justifications_roots and justifications_validators not freed for now as they are not allocated | ||
| allocator.free(self.historical_block_hashes); | ||
| allocator.free(self.justified_slots); |
There was a problem hiding this comment.
we need a ssz.deinit which frees all the slices/allocated stuff recursively, so its better to add that and use that
There was a problem hiding this comment.
These seems not managed by ssz, ssz returns the ownership to caller.
There was a problem hiding this comment.
And I remembered the types ser/dser using ssz lib can't have allocator field, since the ssz lib will reflect all the fields in the types.
There was a problem hiding this comment.
i am not asking it to be managed by ssz, I am asking to add a recursive freeing fn, similar to how serialize
like : sszFree(T: type, object: T)
and free if any slices, lists there recurisvely because the shape of the objects will change so its better implemented as a generic ssz free/denit fn
There was a problem hiding this comment.
It may need more consider as not all the slices allocated such as justifications_roots and justifications_validators. It is better to create a specific issue for this.
There was a problem hiding this comment.
agreed this is a bigger issue and needs to be addressed in ssz as well where slices also need to come from toOwnedSlice, and then a sszFree needs to recursively free slices. @noopur23 create an issue on blockblaz/ssz.zig repo for this
There was a problem hiding this comment.
actually this slice freeing will become irrelevant because we are working on a PR to replace it by ssz list,
@noopur23 add another task in zeam to add "deinit" functions to all ssz types which will use the sszFree fn to be created in ssz lib as above
Signed-off-by: Chen Kai <[email protected]>
Signed-off-by: Chen Kai <[email protected]>
|
|
||
| const Self = @This(); | ||
|
|
||
| pub fn init(self: *Self, allocator: std.mem.Allocator, options: *const NodeOptions) !void { |
There was a problem hiding this comment.
this is a weird form of init where one passes the reference to a self which is unitialized
need @gballet 's opinion on this
There was a problem hiding this comment.
This is a general and better approach in Zig. https://github.com/tigerbeetle/tigerbeetle/blob/main/docs/TIGER_STYLE.md#cache-invalidation
There was a problem hiding this comment.
ok, then we need to move a whole lot of inits to this form
There was a problem hiding this comment.
think it also depends on how large the struct is as the link mentions, if the struct isn't large in size then this form is not necessary.
There was a problem hiding this comment.
right, most of structs in node pkgs are large
|
|
||
| const ascii_art = | ||
| \\ | ||
| \\ ███████╗███████╗ █████╗ ███╗ ███╗ |
There was a problem hiding this comment.
we can probably also ascii convert our logo and add it suitably, @noopur23 create an issue for this
…blaz#198) * fix: make start node test friendly and fix several memory leak Signed-off-by: Chen Kai <[email protected]> * Update pkgs/types/src/lib.zig Co-authored-by: Copilot <[email protected]> * fix: fix more memory leak when error Signed-off-by: Chen Kai <[email protected]> * fix: fix one more error meory leak Signed-off-by: Chen Kai <[email protected]> * Update pkgs/cli/src/node.zig * Update pkgs/cli/src/main.zig * fix: flattening order (blockblaz#208) * update sig size to 4000 bytes as per spec (blockblaz#210) * fix: abstract away network args into a function Signed-off-by: Chen Kai <[email protected]> --------- Signed-off-by: Chen Kai <[email protected]> Co-authored-by: Copilot <[email protected]> Co-authored-by: g11tech <[email protected]> Co-authored-by: Anshal Shukla <[email protected]> Co-authored-by: g11tech <[email protected]>
* fix: make start node test friendly and fix several memory leak (#198) * fix: make start node test friendly and fix several memory leak Signed-off-by: Chen Kai <[email protected]> * Update pkgs/types/src/lib.zig Co-authored-by: Copilot <[email protected]> * fix: fix more memory leak when error Signed-off-by: Chen Kai <[email protected]> * fix: fix one more error meory leak Signed-off-by: Chen Kai <[email protected]> * Update pkgs/cli/src/node.zig * Update pkgs/cli/src/main.zig * fix: flattening order (#208) * update sig size to 4000 bytes as per spec (#210) * fix: abstract away network args into a function Signed-off-by: Chen Kai <[email protected]> --------- Signed-off-by: Chen Kai <[email protected]> Co-authored-by: Copilot <[email protected]> Co-authored-by: g11tech <[email protected]> Co-authored-by: Anshal Shukla <[email protected]> Co-authored-by: g11tech <[email protected]> * refactor: abstract help fn for justifications Fix #182 * fix: fix review comments Signed-off-by: Chen Kai <[email protected]> * fix: resolve merge issue Signed-off-by: Chen Kai <[email protected]> * fix: fix merge error Signed-off-by: Chen Kai <[email protected]> * fix: make justifications deinit more explict Signed-off-by: Chen Kai <[email protected]> * free justifications values * spacing * fix log spacing --------- Signed-off-by: Chen Kai <[email protected]> Co-authored-by: Copilot <[email protected]> Co-authored-by: g11tech <[email protected]> Co-authored-by: Anshal Shukla <[email protected]> Co-authored-by: g11tech <[email protected]>
This PR makes starting node more testing friendly. Such as #194 it need access
BeamNodeto check finalize, but right now can't do it withstartNodefunction in thenode.zig. At the same time the refactor seems makeClock,BeamNodelifecycle more easy. Also try to fix some potential memory leak issue.