nodejs / nodejs/node

net: setKeepAlive() ignores the error returned by the handle

未关闭
#65,529 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

主要语言
JavaScript
星标
122k
派生
37.3k
平均合并
4 天 2 小时
30 天内合并 PR
283

描述

Version

v27.0.0-pre (main)

Platform

Darwin 25.4.0 arm64

Subsystem

net

What steps will reproduce the bug?
const net = require('net');
const server = net.createServer().listen(0, () => {
  const socket = net.connect(server.address().port, () => {
    // Looks like it succeeded
    const returned = socket.setKeepAlive(true, -5000);
    console.log('returns socket:', returned === socket);

    // The handle actually returned EINVAL
    const err = socket._handle.setKeepAlive(true, -5, 1, 10);
    console.log('handle returns:', err);

    socket.destroy();
    server.close();
  });
});

Output:

returns socket: true
handle returns: -22
How often does it reproduce? Is there a required condition?

Every time, for any value the platform rejects.

What is the expected behavior? Why is that the expected behavior?

socket.setKeepAlive() should not report success when the underlying
operation failed. setTypeOfService(), right next to it in the same file,
already does this:

const err = this._handle.setTypeOfService(tos);
if (err && !isWindows) {
  throw new ErrnoException(err, 'setTypeOfService');
}
What do you see instead?

setKeepAlive() discards the return value of the handle call:

this._handle.setKeepAlive(enable, initialDelay, interval, count);

TCPWrap::SetKeepAlive does propagate the error to JS
(args.GetReturnValue().Set(err) in src/tcp_wrap.cc), and
uv_tcp_keepalive_ex() returns UV_EINVAL for a negative delay, so the
information is available. It is simply dropped.

The caller has no way to tell: the return value is the socket either way,
and no error is thrown or emitted.

Additional information

Found while working on #57712 / #65528, which adds a warning for delays
below 1000 ms that are truncated to 0. That change is about values which
are silently reduced; this one is about an error which is silently
discarded, so it seemed better to report it separately.

I have not checked how a value above the platform limit behaves on other
systems. On macOS setKeepAlive(true, 40000000) (40000 s) is accepted by
the handle, so any range check would need per-platform investigation first.

I am happy to open a PR if the direction is agreed. Whether a failure
should throw, like setTypeOfService(), or only emit a warning is a
decision I would rather leave to the team, since throwing would be a
breaking change.

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

从 src/tcp_wrap.cc 中的 socket.setKeepAlive() 路径和 TCPWrap::SetKeepAlive 开始,然后复现 issue 中的负延迟情况。将其处理方式与 setTypeOfService() 进行比较,并调查 macOS 和其他系统上所指出的平台行为。当底层失败不再被静默丢弃,并使用团队批准的错误行为时,即视为完成。

由索引模型根据 Issue 内容生成。

评估

技术栈
cpp, javascript, nodejs
领域
networking
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
活跃
描述清晰度
基本清楚
新手友好度
48/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。