From b9fc0d2908371dc4f7c95c03972d42e290d6e1e0 Mon Sep 17 00:00:00 2001 From: Nameless Date: Fri, 7 Jul 2023 15:08:19 -0500 Subject: [PATCH] std.http: fix leaked connections (#16341) The early return in pool release was causing leaked connections. Closes #16282. --- lib/std/http/Client.zig | 7 +++---- test/standalone/http.zig | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/lib/std/http/Client.zig b/lib/std/http/Client.zig index db576e72b2e0..cefa77c25dab 100644 --- a/lib/std/http/Client.zig +++ b/lib/std/http/Client.zig @@ -92,16 +92,15 @@ pub const ConnectionPool = struct { if (node.data.closing) { node.data.deinit(client); - return client.allocator.destroy(node); } - if (pool.free_len + 1 >= pool.free_size) { + if (pool.free_len >= pool.free_size) { const popped = pool.free.popFirst() orelse unreachable; + pool.free_len -= 1; popped.data.deinit(client); - - return client.allocator.destroy(popped); + client.allocator.destroy(popped); } if (node.data.proxied) { diff --git a/test/standalone/http.zig b/test/standalone/http.zig index 90ba285105ee..18d35d648ace 100644 --- a/test/standalone/http.zig +++ b/test/standalone/http.zig @@ -571,6 +571,30 @@ pub fn main() !void { // connection has been kept alive try testing.expect(client.connection_pool.free_len == 1); + { // issue 16282 + const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/get", .{port}); + defer calloc.free(location); + const uri = try std.Uri.parse(location); + + const total_connections = client.connection_pool.free_size + 64; + var requests = try calloc.alloc(http.Client.Request, total_connections); + defer calloc.free(requests); + + for (0..total_connections) |i| { + var req = try client.request(.GET, uri, .{ .allocator = calloc }, .{}); + req.response.parser.done = true; + req.connection.?.data.closing = false; + requests[i] = req; + } + + for (0..total_connections) |i| { + requests[i].deinit(); + } + + // free connections should be full now + try testing.expect(client.connection_pool.free_len == client.connection_pool.free_size); + } + client.deinit(); killServer(server.socket.listen_address);