From 771ead4e6ffade37f76314a91ca0f55a144af353 Mon Sep 17 00:00:00 2001 From: lazerg Date: Tue, 27 Oct 2026 14:41:44 +0500 Subject: [PATCH 1/2] timers: recheck timer after running next ticks Assisted-by: Claude Code Signed-off-by: lazerg --- lib/internal/timers.js | 8 ++++-- ...t-net-socket-timeout-rearm-in-next-tick.js | 28 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 test/parallel/test-net-socket-timeout-rearm-in-next-tick.js diff --git a/lib/internal/timers.js b/lib/internal/timers.js index 30208253d60f..96a0b5b7f7ac 100644 --- a/lib/internal/timers.js +++ b/lib/internal/timers.js @@ -633,10 +633,14 @@ function getTimerCallbacks(runNextTicks) { return; } - if (ranAtLeastOneTimer) + if (ranAtLeastOneTimer) { runNextTicks(); - else + // The ticks may have cleared or rescheduled this timer. + if (L.peek(list) !== timer || now - timer._idleStart < msecs) + continue; + } else { ranAtLeastOneTimer = true; + } // The actual logic for when a timeout happens. L.remove(timer); diff --git a/test/parallel/test-net-socket-timeout-rearm-in-next-tick.js b/test/parallel/test-net-socket-timeout-rearm-in-next-tick.js new file mode 100644 index 000000000000..5b6a5fd7ca48 --- /dev/null +++ b/test/parallel/test-net-socket-timeout-rearm-in-next-tick.js @@ -0,0 +1,28 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const net = require('net'); + +// Re-arming a socket timeout from a nextTick queued by a timer that runs just +// before it in the same timer list must replace the old timeout. + +const server = net.createServer().listen(0, common.mustCall(() => { + const socket = net.connect(server.address().port, common.mustCall(() => { + let rearmed = false; + + setTimeout(common.mustCall(() => { + process.nextTick(() => { + socket.setTimeout(50); + setImmediate(() => { rearmed = true; }); + }); + }), 1); + socket.setTimeout(1); + + socket.on('timeout', common.mustCall(() => { + assert.ok(rearmed); + socket.destroy(); + server.close(); + })); + })); +})); From cc1f25f1b8b86c16345815b2cdc6c0434d38b424 Mon Sep 17 00:00:00 2001 From: lazerg Date: Tue, 27 Oct 2026 16:35:09 +0500 Subject: [PATCH 2/2] test: use longer timers in socket timeout rearm test Assisted-by: Claude Code Signed-off-by: lazerg --- test/parallel/test-net-socket-timeout-rearm-in-next-tick.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/parallel/test-net-socket-timeout-rearm-in-next-tick.js b/test/parallel/test-net-socket-timeout-rearm-in-next-tick.js index 5b6a5fd7ca48..64dcd8257c03 100644 --- a/test/parallel/test-net-socket-timeout-rearm-in-next-tick.js +++ b/test/parallel/test-net-socket-timeout-rearm-in-next-tick.js @@ -13,11 +13,11 @@ const server = net.createServer().listen(0, common.mustCall(() => { setTimeout(common.mustCall(() => { process.nextTick(() => { - socket.setTimeout(50); + socket.setTimeout(500); setImmediate(() => { rearmed = true; }); }); - }), 1); - socket.setTimeout(1); + }), 300); + socket.setTimeout(300); socket.on('timeout', common.mustCall(() => { assert.ok(rearmed);