mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
node:net: fix handle leak (#22913)
This commit is contained in:
@@ -80,7 +80,7 @@ function getNodeParallelTestTimeout(testPath) {
|
||||
if (testPath.includes("test-dns")) {
|
||||
return 90_000;
|
||||
}
|
||||
return 10_000;
|
||||
return 20_000;
|
||||
}
|
||||
|
||||
process.on("SIGTRAP", () => {
|
||||
|
||||
@@ -111,7 +111,7 @@ pub fn NewSocket(comptime ssl: bool) type {
|
||||
pub fn doConnect(this: *This, connection: Listener.UnixOrHost) !void {
|
||||
bun.assert(this.socket_context != null);
|
||||
this.ref();
|
||||
errdefer this.deref();
|
||||
defer this.deref();
|
||||
|
||||
switch (connection) {
|
||||
.host => |c| {
|
||||
|
||||
77
test/js/node/net/handle-leak.test.ts
Normal file
77
test/js/node/net/handle-leak.test.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { expect } from "bun:test";
|
||||
import { isASAN, isWindows } from "harness";
|
||||
import * as net from "node:net";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { setTimeout } from "node:timers/promises";
|
||||
|
||||
const listen_path = join(tmpdir(), "test-net-successful-connection-handle-leak.sock");
|
||||
|
||||
const { promise, resolve } = Promise.withResolvers();
|
||||
const server = net
|
||||
.createServer()
|
||||
.listen(listen_path)
|
||||
.on("listening", () => resolve());
|
||||
await promise;
|
||||
const address = server.address();
|
||||
console.log("server address", address);
|
||||
|
||||
let started;
|
||||
|
||||
started = 0;
|
||||
while (started < 50_000) {
|
||||
const promises: Promise<void>[] = [];
|
||||
for (let i = 0; i < 100; i++) {
|
||||
const { promise, resolve, reject } = Promise.withResolvers<void>();
|
||||
const socket = net
|
||||
.connect({ path: listen_path })
|
||||
.on("connect", () => {
|
||||
socket.on("close", () => resolve());
|
||||
socket.end();
|
||||
})
|
||||
.on("error", e => {
|
||||
reject(e);
|
||||
});
|
||||
|
||||
promises.push(promise);
|
||||
started++;
|
||||
}
|
||||
await Promise.all(promises);
|
||||
await setTimeout(1);
|
||||
console.log(`Completed ${started} connections. RSS: ${(process.memoryUsage.rss() / 1024 / 1024) | 0} MB`);
|
||||
}
|
||||
|
||||
Bun.gc(true);
|
||||
const warmup_rss = process.memoryUsage.rss();
|
||||
|
||||
started = 0;
|
||||
while (started < 100_000) {
|
||||
const promises: Promise<void>[] = [];
|
||||
for (let i = 0; i < 100; i++) {
|
||||
const { promise, resolve, reject } = Promise.withResolvers<void>();
|
||||
const socket = net
|
||||
.connect({ path: listen_path })
|
||||
.on("connect", () => {
|
||||
socket.on("close", () => resolve());
|
||||
socket.end();
|
||||
})
|
||||
.on("error", e => {
|
||||
reject(e);
|
||||
});
|
||||
|
||||
promises.push(promise);
|
||||
started++;
|
||||
}
|
||||
await Promise.all(promises);
|
||||
await setTimeout(1);
|
||||
console.log(`Completed ${started} connections. RSS: ${(process.memoryUsage.rss() / 1024 / 1024) | 0} MB`);
|
||||
}
|
||||
|
||||
const post_rss = process.memoryUsage.rss();
|
||||
|
||||
server.close();
|
||||
|
||||
let margin = 1024 * 1024 * 15;
|
||||
if (isWindows) margin = 1024 * 1024 * 20;
|
||||
if (isASAN) margin = 1024 * 1024 * 60;
|
||||
expect(post_rss - warmup_rss).toBeLessThan(margin);
|
||||
Reference in New Issue
Block a user