authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-15 11:01:03-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-29 06:20:49-07:00
log870a682cd84e49b2213dffd59c9848d7fd12b7a1
treea49ad9b1e4fe1ff4a513925398b04893dfbc8a0c
parent426a377c7b6a64092ab0b45710dc428da60557a1

std.Io.net.HostName.connect: fix resource leaks

Must free other succeeded connections that lost the race.

2 files changed, 25 insertions(+), 9 deletions(-)

BRANCH_TODO+1
......@@ -18,3 +18,4 @@
1818* migrate child process into std.Io
1919* eliminate std.Io.poll (it should be replaced by "select" functionality)
2020* finish moving all of std.posix into Threaded
21* TCP fastopen - sends initial payload along with connection. can be done for idempotent http requests
lib/std/Io/net/HostName.zig+24-9
......@@ -210,25 +210,38 @@ pub fn connect(
210210 var connect_many_queue: Io.Queue(ConnectManyResult) = .init(&connect_many_buffer);
211211
212212 var connect_many = io.async(connectMany, .{ host_name, io, port, &connect_many_queue, options });
213 defer connect_many.cancel(io);
213 var saw_end = false;
214 defer {
215 connect_many.cancel(io);
216 if (!saw_end) while (true) switch (connect_many_queue.getOneUncancelable(io)) {
217 .connection => |loser| if (loser) |s| s.closeConst(io) else |_| continue,
218 .end => break,
219 };
220 }
214221
215222 var aggregate_error: ConnectError = error.UnknownHostName;
216223
217224 while (connect_many_queue.getOne(io)) |result| switch (result) {
218225 .connection => |connection| if (connection) |stream| return stream else |err| switch (err) {
219 error.SystemResources => |e| return e,
220 error.OptionUnsupported => |e| return e,
221 error.ProcessFdQuotaExceeded => |e| return e,
222 error.SystemFdQuotaExceeded => |e| return e,
223 error.Canceled => |e| return e,
226 error.SystemResources,
227 error.OptionUnsupported,
228 error.ProcessFdQuotaExceeded,
229 error.SystemFdQuotaExceeded,
230 error.Canceled,
231 => |e| return e,
232
224233 error.WouldBlock => return error.Unexpected,
234
225235 else => |e| aggregate_error = e,
226236 },
227237 .end => |end| {
238 saw_end = true;
228239 try end;
229240 return aggregate_error;
230241 },
231 } else |err| return err;
242 } else |err| switch (err) {
243 error.Canceled => |e| return e,
244 }
232245}
233246
234247pub const ConnectManyResult = union(enum) {
......@@ -255,7 +268,6 @@ pub fn connectMany(
255268 });
256269
257270 var group: Io.Group = .init;
258 defer group.cancel(io);
259271
260272 while (lookup_queue.getOne(io)) |dns_result| switch (dns_result) {
261273 .address => |address| group.async(io, enqueueConnection, .{ address, io, results, options }),
......@@ -266,7 +278,10 @@ pub fn connectMany(
266278 return;
267279 },
268280 } else |err| switch (err) {
269 error.Canceled => |e| results.putOneUncancelable(io, .{ .end = e }),
281 error.Canceled => |e| {
282 group.cancel(io);
283 results.putOneUncancelable(io, .{ .end = e });
284 },
270285 }
271286}
272287