From 460b05353a13716bbe3984fb88051798914e5b1c Mon Sep 17 00:00:00 2001 From: chenyuebiao Date: Sun, 26 Apr 2026 21:21:13 +0800 Subject: [PATCH] dgram: support UV_UDP_LINUX_RECVERR for udp --- doc/api/dgram.md | 3 +++ lib/dgram.js | 6 +++++- src/udp_wrap.cc | 1 + test/parallel/test-dgram-recvErr.js | 23 +++++++++++++++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-dgram-recvErr.js diff --git a/doc/api/dgram.md b/doc/api/dgram.md index e8efbcfd262b0e..4834d162c1d9f1 100644 --- a/doc/api/dgram.md +++ b/doc/api/dgram.md @@ -968,6 +968,9 @@ changes: specified by the NAT. * `sendBlockList` {net.BlockList} `sendBlockList` can be used for disabling outbound access to specific IP addresses, IP ranges, or IP subnets. + * `recvErr` {boolean} When `true` the socket will emit an error event + if the peer is unreachable(On Linux only). + **Default:** `false`. * `callback` {Function} Attached as a listener for `'message'` events. Optional. * Returns: {dgram.Socket} diff --git a/lib/dgram.js b/lib/dgram.js index 19b8300e315be5..88493ceb7dfc7f 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -76,7 +76,7 @@ const { FastBuffer } = require('internal/buffer'); const { UV_UDP_REUSEADDR } = internalBinding('constants').os; const { - constants: { UV_UDP_IPV6ONLY, UV_UDP_REUSEPORT }, + constants: { UV_UDP_IPV6ONLY, UV_UDP_REUSEPORT, UV_UDP_LINUX_RECVERR }, UDP, SendWrap, } = internalBinding('udp_wrap'); @@ -157,6 +157,7 @@ function Socket(type, listener) { queue: undefined, reuseAddr: options?.reuseAddr, // Use UV_UDP_REUSEADDR if true. reusePort: options?.reusePort, + recvErr: options?.recvErr, ipv6Only: options?.ipv6Only, recvBufferSize, sendBufferSize, @@ -378,6 +379,9 @@ Socket.prototype.bind = function(port_, address_ /* , callback */) { exclusive = true; flags |= UV_UDP_REUSEPORT; } + if (state.recvErr) { + flags |= UV_UDP_LINUX_RECVERR; + } if (cluster.isWorker && !exclusive) { bindServerHandle(this, { diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc index b5e732dd6f1cb4..148d82eab59689 100644 --- a/src/udp_wrap.cc +++ b/src/udp_wrap.cc @@ -233,6 +233,7 @@ void UDPWrap::Initialize(Local target, NODE_DEFINE_CONSTANT(constants, UV_UDP_IPV6ONLY); NODE_DEFINE_CONSTANT(constants, UV_UDP_REUSEADDR); NODE_DEFINE_CONSTANT(constants, UV_UDP_REUSEPORT); + NODE_DEFINE_CONSTANT(constants, UV_UDP_LINUX_RECVERR); target->Set(context, env->constants_string(), constants).Check(); diff --git a/test/parallel/test-dgram-recvErr.js b/test/parallel/test-dgram-recvErr.js new file mode 100644 index 00000000000000..6a82d1334d012f --- /dev/null +++ b/test/parallel/test-dgram-recvErr.js @@ -0,0 +1,23 @@ +'use strict'; +const common = require('../common'); +const dgram = require('dgram'); + +if (process.platform !== 'linux') { + common.skip('Only Linux is supported'); +} + +const socket = dgram.createSocket({ recvErr: true, type: 'udp4' }); + +function onError(err) { + console.error('UV_UDP_LINUX_RECVERR is unsupported: ', err); + socket.close(); +} + +socket.on('error', onError); +socket.bind(0, common.mustCall(() => { + socket.off('error', onError); + socket.on('error', common.mustCall(() => { + socket.close(); + })); + socket.send('hello', 9999, '127.0.0.1'); +}));