From cb39509bf7146aa70c472412d8007d2ac43febb0 Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Fri, 6 Sep 2024 16:16:33 +0900 Subject: [PATCH 1/2] fix(ext/node): delay accept() call 2 ticks in net.Server#listen --- .../polyfills/internal_binding/tcp_wrap.ts | 10 +++++++++- tests/unit_node/net_test.ts | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/ext/node/polyfills/internal_binding/tcp_wrap.ts b/ext/node/polyfills/internal_binding/tcp_wrap.ts index 9897bccd06d3da..4b57a7e1ecdf24 100644 --- a/ext/node/polyfills/internal_binding/tcp_wrap.ts +++ b/ext/node/polyfills/internal_binding/tcp_wrap.ts @@ -45,6 +45,7 @@ import { INITIAL_ACCEPT_BACKOFF_DELAY, MAX_ACCEPT_BACKOFF_DELAY, } from "ext:deno_node/internal_binding/_listen.ts"; +import { nextTick } from "ext:deno_node/_next_tick.ts"; /** The type of TCP socket. */ enum socketType { @@ -228,7 +229,14 @@ export class TCP extends ConnectionWrap { this.#port = address.port; this.#listener = listener; - this.#accept(); + + // TODO(kt3k): Delays the accept() call 2 ticks. Deno.Listener can't be closed + // synchronously when accept() is called. By delaying the accept() call, + // the user can close the server synchronously in the callback of listen(). + // This workaround enables `npm:detect-port` to work correctly. + // Remove these nextTick calls when the below issue resolved: + // https://github.com/denoland/deno/issues/25480 + nextTick(nextTick, () => this.#accept()); return 0; } diff --git a/tests/unit_node/net_test.ts b/tests/unit_node/net_test.ts index 708d06386caf38..5cf9bd124f9338 100644 --- a/tests/unit_node/net_test.ts +++ b/tests/unit_node/net_test.ts @@ -228,3 +228,21 @@ Deno.test("[node/net] BlockList doesn't leak resources", () => { blockList.addAddress("1.1.1.1"); assert(blockList.check("1.1.1.1")); }); + +Deno.test("[node/net] net.Server can listen on the same port immediately after it's closed", async () => { + const serverClosed = Promise.withResolvers(); + const server = net.createServer(); + server.on("error", (e) => { + console.error(e); + }); + server.listen(0, () => { + const port = (server.address() as any).port; + server.close(); + server.listen(port, () => { + server.close(() => { + serverClosed.resolve(); + }); + }); + }) + await serverClosed.promise; +}); From 6af4a4795fd67c461a9824ed142d76e922a62dce Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Fri, 6 Sep 2024 16:43:04 +0900 Subject: [PATCH 2/2] fmt, fix lint --- tests/unit_node/net_test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/unit_node/net_test.ts b/tests/unit_node/net_test.ts index 5cf9bd124f9338..8196874f301111 100644 --- a/tests/unit_node/net_test.ts +++ b/tests/unit_node/net_test.ts @@ -236,13 +236,14 @@ Deno.test("[node/net] net.Server can listen on the same port immediately after i console.error(e); }); server.listen(0, () => { - const port = (server.address() as any).port; + // deno-lint-ignore no-explicit-any + const { port } = server.address() as any; server.close(); server.listen(port, () => { server.close(() => { serverClosed.resolve(); }); }); - }) + }); await serverClosed.promise; });