Hello all,
I ran into this bug while working on a project and got down to this minimal reproduction:
const std = @import("std");
fn getClient(a: std.mem.Allocator) !std.http.Client {
// Initialize client
var client: std.http.Client = .{ .allocator = a };
// Perform a fetch
_ = try client.fetch(.{ .location = .{ .url = "https://smlavine.com" } });
// Return client
return client;
}
pub fn main() !void {
var gpa: std.heap.DebugAllocator(.{}) = .init;
defer _ = gpa.deinit();
const a = gpa.allocator();
var client = try getClient(a);
client.deinit();
}
Results in this segfault:
minimal-crash-repro$ zig run src/fetch-sections.zig
Segmentation fault at address 0x7fdbd05ef000
/usr/lib/zig/std/mem/Allocator.zig:430:26: 0x1112c38 in free__anon_18432 (std.zig)
@memset(non_const_ptr[0..bytes_len], undefined);
^
/usr/lib/zig/std/http/Client.zig:351:21: 0x11a1607 in destroy (std.zig)
gpa.free(base[0..allocLen(c.client, c.host_len)]);
^
/usr/lib/zig/std/http/Client.zig:407:28: 0x11886f8 in destroy (std.zig)
tls.destroy();
^
/usr/lib/zig/std/http/Client.zig:186:31: 0x117439f in deinit (std.zig)
connection.destroy();
^
/usr/lib/zig/std/http/Client.zig:1280:34: 0x1169ec7 in deinit (std.zig)
client.connection_pool.deinit();
^
/home/smlavine/Code/projects/rit-class-stats/src/fetch-sections.zig:20:18: 0x1165847 in main (fetch-sections.zig)
client.deinit();
^
/usr/lib/zig/std/start.zig:627:37: 0x1166049 in posixCallMainAndExit (std.zig)
const result = root.main() catch |err| {
^
/usr/lib/zig/std/start.zig:232:5: 0x1165351 in _start (std.zig)
asm volatile (switch (native_arch) {
^
???:?:?: 0x0 in ??? (???)
Aborted (core dumped) zig run src/fetch-sections.zig
If I remove the fetch() call, then there is no segfault.
If I remove the Client.deinit() call, there is a leak.
Glancing at the error trace – is there an internal pointer inside Client that is incorrectly outliving the move?
What am I missing here? Am I doing something wrong? On version 0.15.2. Help appreciated, thanks.