Zig package behaving differently on two systems

I am working on this project, developing on one machine, deploying it to another. Out of curiosity I wanted to run some tests on the deployment server. These tests are dependent on outside factors (eth RPC), and by accident I ran them without them properly configured. This resulted in a test failing, and leaking memory on the server.

FAILED
/root/.cache/zig/p/zabi-0.16.1-UB4phl86SABdBvFceyCgBARQTki8rNko7MLouY-TeGVQ/src/clients/IPC.zig:223:13: 0x167e744 in connect (test)
            return error.FailedToConnect;
            ^
/root/.cache/zig/p/zabi-0.16.1-UB4phl86SABdBvFceyCgBARQTki8rNko7MLouY-TeGVQ/src/clients/IPC.zig:183:30: 0x167de09 in init (test)
    self.ipc_reader.stream = try self.connect(opts.network_config.endpoint.path);
                             ^
/root/my-project/test/modules/TokenModule.test.zig:14:18: 0x167d6e8 in test.Init, load data, and deinit (test)
    var client = try IpcClient.init(.{
                 ^
error(gpa): memory address 0x74ddd9901000 leaked: 
/root/.cache/zig/p/zabi-0.16.1-UB4phl86SABdBvFceyCgBARQTki8rNko7MLouY-TeGVQ/src/clients/IPC.zig:174:43: 0x167db20 in init (test)
        .buffer = try opts.allocator.alloc(u8, opts.growth_rate orelse std.math.maxInt(u16)),
                                          ^
/root/my-project/test/modules/TokenModule.test.zig:14:36: 0x167d6c3 in test.Init, load data, and deinit (test)
    var client = try IpcClient.init(.{
                                   ^
/root/my-project/build/test_runner.zig:159:29: 0x128c820 in main (test)
        if (test_runner.func()) |_| try runner.writeSuccess() else |err| switch (err) {
                            ^
/root/.zvm/0.14.1/lib/std/start.zig:660:37: 0x128f667 in main (test)
            const result = root.main() catch |err| {
                                    ^

LEAKED
    Tests: 6 passed
    Tests: 1 failed
    Tests: 0 skipped
    Tests: 1 leaked

Okay, I guess there is an errdefer missing somewhere. But when I tried to recreate the same state on my development machine, I get the same error, but not a mem leak:

FAILED
/home/nixos/.cache/zig/p/zabi-0.16.1-UB4phl86SABdBvFceyCgBARQTki8rNko7MLouY-TeGVQ/src/clients/IPC.zig:226:13: 0x1673454 in connect (test)
            return error.FailedToConnect;
            ^
/home/nixos/.cache/zig/p/zabi-0.16.1-UB4phl86SABdBvFceyCgBARQTki8rNko7MLouY-TeGVQ/src/clients/IPC.zig:186:30: 0x1672aef in init (test)
    self.ipc_reader.stream = try self.connect(opts.network_config.endpoint.path);
                             ^
/home/nixos/code/my-project/test/modules/TokenModule.test.zig:14:18: 0x16723a8 in test.Init, load data, and deinit (test)
    var client = try IpcClient.init(.{
                 ^

    Tests: 6 passed
    Tests: 1 failed
    Tests: 0 skipped
    Tests: 0 leaked

Across the two machines, I am using the same:

  1. Zig version - 0.14.1
  2. Git repo and branch

Since the leak is occuring in a third party library, it makes sense to check out it’s versioning, but it appears to be the same:

server:
zabi-0.16.1-UB4phl86SABdBvFceyCgBARQTki8rNko7MLouY-TeGVQ
development:
zabi-0.16.1-UB4phl86SABdBvFceyCgBARQTki8rNko7MLouY-TeGVQ

But for some reason, I do not understand, the Zig compiler is referring to the same lines of code apparently in different places on the two machines:

server:
.../IPC.zig:183:30: 0x167de09 in init (test) self.ipc_reader.stream = try self.connect(opts.network_config.endpoint.path);
development:
...IPC.zig:186:30: 0x1672aef in init (test) self.ipc_reader.stream = try self.connect(opts.network_config.endpoint.path);

What am I missing here?

Edit:

I have checked the sha256sums of the two files, and they aren’t matching. When I checked for diffs, I got this:

+++ b/root/.cache/zig/p/zabi-0.16.1-UB4phl86SABdBvFceyCgBARQTki8rNko7MLouY-TeGVQ/src/clients/IPC.zig
@@ -169,12 +169,9 @@ pub fn init(opts: InitOptions) InitErrors!*IPC {
         self.sub_channel.deinit();
     }
 
-    const buffer = try opts.allocator.alloc(u8, opts.growth_rate orelse std.math.maxInt(u16));
-    errdefer opts.allocator.free(buffer);
-
     self.ipc_reader = .{
         .allocator = opts.allocator,
-        .buffer = buffer,
+        .buffer = try opts.allocator.alloc(u8, opts.growth_rate orelse std.math.maxInt(u16)),
         .growth_rate = opts.growth_rate orelse std.math.maxInt(u16),
         .stream = undefined,
         .closed = false,

Okay so it’s not the same code? I am completely lost. :confused:

If I had to venture a guess, you encountered this issue in the past, edited the dependency in-place directly in your cache, and then forgot about it.

4 Likes

Damn it! I was sure I removed all the cache. After rm -rf-ing the .cache/zig I got the expected results. Thanks!

Feeling like an idiot for summoning you of all people for such a dumb problem xD

3 Likes