Skip to content

fix(relay): enlarge sender send buffer to prevent slow-client kicks - #286

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:develop/snipefrom
wangrong1069:agent/pms-bug-bot/4ed5286b73e5
Oct 15, 2026
Merged

deepin-bot[bot] merged 1 commit into
linuxdeepin:develop/snipefrom
wangrong1069:agent/pms-bug-bot/4ed5286b73e5

Conversation

@wangrong1069

@wangrong1069 wangrong1069 commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Root Cause Analysis

The relay dispatcher's socketpair only enlarged the receive buffer on the client end (fds[1]) via SO_RCVBUFFORCE/SO_RCVBUF, but left the sender end (fds[0]) at the default send buffer size. When event bursts exhaust the sender's kernel send queue, the non-blocking send() in event_relay_dispatcher_send() returns EAGAIN/EWOULDBLOCK, causing the client to be kicked with "relay: slow client fd %d, kicking".

Key evidence: src/dispatcher/event_relay_dispatcher.c:107-118 only configures SO_RCVBUF on fds[1]; :144 sends via fds[0]; :148 kicks on EAGAIN. The same repo's event_dispatcher.c already applies SO_SNDBUF on its sender end (commit 36b42fb).

Fix

Add SO_SNDBUFFORCE (8 MiB) on fds[0] with fallback to SO_SNDBUF, mirroring the existing receive buffer configuration on fds[1]. The CAP_NET_ADMIN capability already granted by the systemd unit (added in commit d92fea0) satisfies SO_SNDBUFFORCE for both directions. No API change, no logic change — only adds buffer configuration code.

Change Safety Assessment

Code Safety

  • Risk Level: Low
  • Target lines were introduced by the initial feature commit (62b9db7), not a previous bug fix; this change does not revert any historical fix.
  • The function signature event_relay_dispatcher_get_event_channel() is unchanged; all 19 callers (server module + tests) use only the return value and are unaffected.

Business Impact Scope

Affects the deepin-anything-server event relay broadcast functionality. When file system events burst (e.g., bulk file operations), relay clients consuming events at a slower rate will no longer be prematurely disconnected due to sender buffer exhaustion. The fix improves relay stability under high event throughput scenarios.

Verification Suggestion

  1. Trigger a burst of file system events (e.g., create/delete many files simultaneously) with a slow relay client connected, verify the client is not kicked with "slow client" error.
  2. Verify multiple relay clients receive events normally after the fix.

根因分析

relay 调度器的 socketpair 创建后只放大了客户端端 fds[1] 的接收缓冲区(SO_RCVBUFFORCE/SO_RCVBUF),没有放大服务端发送端 fds[0] 的发送缓冲区。突发事件耗尽发送端内核发送队列后,event_relay_dispatcher_send() 的非阻塞 send() 返回 EAGAIN/EWOULDBLOCK,代码随即踢出客户端并输出 "relay: slow client fd %d, kicking"。

关键证据:src/dispatcher/event_relay_dispatcher.c:107-118 只配置了 fds[1] 的 SO_RCVBUF;:144 通过 fds[0] 发送;:148 收到 EAGAIN 后踢出。同仓库 event_dispatcher.c 已在发送端配置 SO_SNDBUF(commit 36b42fb)。

修复方案

为 fds[0] 增加 SO_SNDBUFFORCE(8 MiB)发送缓冲区,失败时回退 SO_SNDBUF,与现有接收端配置对称。systemd unit 中已授予的 CAP_NET_ADMIN(commit d92fea0)同时满足双向 force 配置需求。无 API 变化,无逻辑变化,仅新增缓冲区配置代码。

改动安全评估

代码安全评估

  • 风险等级: 低风险
  • 目标行由初始功能提交(62b9db7)引入,非历史 bug 修复产物,本次修改不会撤销任何已有修复。
  • 函数签名 event_relay_dispatcher_get_event_channel() 未改变,全部 19 处调用者(服务端模块 + 测试)仅使用返回值,不受影响。

业务影响范围

影响 deepin-anything-server 事件中继广播功能。文件系统事件突发时(如批量文件操作),消费速度较慢的 relay 客户端不再因发送端缓冲区耗尽而被提前断开。修复提升了高事件吞吐场景下的 relay 稳定性。

验证建议

  1. 触发文件系统事件突发(如同时创建/删除大量文件),连接慢速 relay 客户端,验证客户端不再因 "slow client" 错误被踢出。
  2. 验证多个 relay 客户端在修复后正常接收事件。

Summary by Sourcery

Bug Fixes:

  • Prevent relay clients from being disconnected during event bursts by enlarging the sender-side socket buffer and falling back to the standard send-buffer setting when necessary.

@sourcery-ai

sourcery-ai Bot commented Oct 15, 2026

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

The relay dispatcher now enlarges the sender-side socket buffer, with a capability-aware fallback, so burst traffic is less likely to produce EAGAIN and disconnect slow clients; no API or dispatch logic changes are introduced.

Sequence diagram for relay burst buffering and slow-client protection

sequenceDiagram
    participant Dispatcher
    participant SenderSocket
    participant ClientSocket
    participant RelayClient

    Dispatcher->>SenderSocket: setsockopt(SO_SNDBUFFORCE, 8 MiB)
    alt SO_SNDBUFFORCE fails
        Dispatcher->>SenderSocket: setsockopt(SO_SNDBUF, 8 MiB)
    end
    Dispatcher->>ClientSocket: setsockopt(SO_RCVBUFFORCE, 8 MiB)
    Dispatcher->>SenderSocket: send(event)
    SenderSocket->>ClientSocket: buffered relay event burst
    ClientSocket->>RelayClient: deliver events
    Note over SenderSocket,RelayClient: Larger sender buffer reduces EAGAIN/EWOULDBLOCK slow-client kicks
Loading

File-Level Changes

Change Details Files
Increase the relay socketpair sender-side kernel buffer to reduce non-blocking send failures during event bursts.
  • Configure an 8 MiB SO_SNDBUFFORCE buffer on fds[0].
  • Fall back to SO_SNDBUF when the force-enabled option fails, with diagnostic logging.
  • Correct the receive-buffer comment to reference rmem_max rather than wmem_max; retain the existing client receive-buffer behavior.
src/dispatcher/event_relay_dispatcher.c

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

The relay dispatcher's socketpair only enlarged the receive buffer on
the client end (fds[1]) via SO_RCVBUFFORCE/SO_RCVBUF, but left the
sender end (fds[0]) at the default send buffer size. When event bursts
exhaust the sender's kernel send queue, the non-blocking send() in
event_relay_dispatcher_send() returns EAGAIN/EWOULDBLOCK, causing the
client to be kicked with "relay: slow client fd %d, kicking".

Fix: add SO_SNDBUFFORCE (8 MiB) on fds[0] with fallback to SO_SNDBUF,
mirroring the existing receive buffer configuration on fds[1]. The
CAP_NET_ADMIN capability already granted by the systemd unit (added in
the previous fix) satisfies SO_SNDBUFFORCE for both directions.

PMS: TASK-395961

Log: 增大relay发送端缓冲区,防止突发事件时慢客户端被踢出
Influence: relay事件广播在突发场景下的稳定性提升
@wangrong1069
wangrong1069 force-pushed the agent/pms-bug-bot/4ed5286b73e5 branch from 83f3b4c to 90e87bf Compare October 15, 2026 03:06
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

AI 代码审查报告

项目: linuxdeepin/deepin-anything
PR: #286
提交: fix(relay): enlarge sender send buffer to prevent slow-client kicks
作者: wangrong1069
分支: agent/pms-bug-bot/4ed5286b73e5 → develop/snipe
审查模式: 全量分析
审查时间: 2026-10-15


总体评价

总分: 100/100 | 风险等级: 无风险

本次提交修复了 relay 事件分发器中发送端缓冲区未增大的问题。代码修改质量优秀,新增的发送端缓冲区配置逻辑与已有的接收端配置完全对称,注释详尽,错误处理完善。未发现任何安全漏洞或代码质量问题。


漏洞统计

指标 数量
当前漏洞总数 0
新增漏洞 0
修复漏洞 0
持平漏洞 0

漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个


四维度评分

维度 评分 满分 状态 评价
语法逻辑 25 25 ✓ 语法正确,逻辑清晰
代码质量 25 25 ✓ 代码结构清晰,注释完整
代码性能 20 20 ✓ 性能良好,资源使用合理
代码安全 30 30 ✓ 存在0个安全漏洞

维度1:语法逻辑(25/25 ✓)

评价: 语法正确,逻辑清晰

变更分析:

  1. 注释修复(第108行):将 wmem_max 修正为 rmem_max。SO_RCVBUFFORCE 绕过的是 rmem_max(接收缓冲区系统限制),原注释中的 wmem_max(发送缓冲区限制)是错误的,此修复正确。

  2. 新增发送端缓冲区配置(第120-131行):

    • 变量声明 int snd_buf_size = 8 << 20; 位置合理,在接收缓冲区配置之后
    • setsockopt(fds[0], SOL_SOCKET, SO_SNDBUFFORCE, &snd_buf_size, sizeof(snd_buf_size)) 参数正确
    • 错误处理逻辑完整:先尝试 SO_SNDBUFFORCE,失败后回退到 SO_SNDBUF
    • 无内存泄漏、空指针解引用或竞态条件风险

潜在问题: 无


维度2:代码质量(25/25 ✓)

评价: 代码结构清晰,注释完整

变更分析:

  1. 注释完整性(5/5):新增代码包含详尽的多行注释,解释了:

    • 修改原因:防止事件突发时发送队列耗尽触发 EAGAIN/EWOULDBLOCK
    • 技术细节:SO_SNDBUFFORCE 绕过 wmem_max 限制
    • 权限要求:需要 CAP_NET_ADMIN(已在 systemd unit 中配置)
    • 回退机制:SO_SNDBUF 遵循 wmem_max 限制
  2. 代码重复(5/5):新增代码与接收端缓冲区配置(第110-118行)结构相似,但操作对象不同(fds[0] vs fds[1])、选项不同(SO_SNDBUFFORCE vs SO_RCVBUFFORCE),属于合理的模式复用而非冗余复制。

  3. 结构合理性(5/5):函数内代码组织清晰——先配置接收缓冲区,再配置发送缓冲区,最后存储 fd。逻辑顺序合理。

  4. 调试信息清理(5/5):日志级别使用恰当:

    • g_info:用于 SO_SNDBUFFORCE 失败回退(需要管理员关注)
    • g_debug:用于 SO_SNDBUF 二级失败(调试级别即可)
    • 无残留调试代码
  5. 命名规范(5/5):snd_buf_size 命名清晰,与已有的 rcv_buf_size 保持一致的命名风格。

潜在问题: 无


维度3:代码性能(20/20 ✓)

评价: 性能良好,资源使用合理

变更分析:

  1. 性能提升:此修改直接解决了事件突发时发送端 EAGAIN/EWOULDBLOCK 的问题。通过将发送缓冲区从系统默认值(通常 208KB)增大到 8 MiB,显著降低了慢客户端被误踢的概率。

  2. 资源使用:setsockopt 仅在 event_relay_dispatcher_get_event_channel 创建新通道时调用一次,不在事件发送的热路径中,无运行时性能开销。

  3. 缓冲区大小:8 MiB 与接收端缓冲区大小一致,对于事件突发场景是合理的。使用 8 << 20 表达式清晰可读。

  4. 回退机制:当 SO_SNDBUFFORCE 不可用时(无 CAP_NET_ADMIN),回退到 SO_SNDBUF,虽然缓冲区可能小于 8 MiB(受 wmem_max 限制),但仍尝试增大,不会导致功能失败。

潜在问题: 无


维度4:代码安全(30/30 ✓)

评价: 存在0个安全漏洞

安全分析:

  1. 输入校验:缓冲区大小 8 << 20 是编译时常量,不涉及用户输入,无注入风险。

  2. 权限安全:SO_SNDBUFFORCE 需要 CAP_NET_ADMIN 权限,已在 systemd unit 中配置。注释中明确说明了权限来源,无权限提升风险。

  3. 信息泄露:错误日志仅记录 strerror(errno) 返回的系统错误信息,不包含敏感数据。

  4. 缓冲区安全:setsockopt 的参数 &snd_buf_size 和 sizeof(snd_buf_size) 使用正确,无缓冲区溢出风险。

  5. 资源管理:fds[0] 在函数后续被添加到 socket_list(第134行),由 close_fd 回调管理生命周期,无资源泄漏。

漏洞对比统计: 新增漏洞 0 个,减少漏洞 0 个,持平 0 个

安全漏洞清单: 无


代码变更详情

文件: src/dispatcher/event_relay_dispatcher.c

函数: event_relay_dispatcher_get_event_channel

变更1 - 注释修复(第108行):

-     * SO_RCVBUFFORCE bypasses the system wmem_max limit (requires CAP_NET_ADMIN
+     * SO_RCVBUFFORCE bypasses the system rmem_max limit (requires CAP_NET_ADMIN

修复注释中的术语错误:SO_RCVBUFFORCE 绕过的是 rmem_max(接收缓冲区限制),而非 wmem_max(发送缓冲区限制)。

变更2 - 新增发送端缓冲区配置(第120-131行):

/* Enlarge send buffer on the sender end so bursts of events don't
 * exhaust the kernel send queue and trigger EAGAIN/EWOULDBLOCK, which
 * would cause the slow-client kick.  SO_SNDBUFFORCE bypasses wmem_max
 * (requires CAP_NET_ADMIN, already granted via the systemd unit).
 * Falls back to SO_SNDBUF which respects wmem_max. */
int snd_buf_size = 8 << 20;  /* 8 MiB */
if (setsockopt(fds[0], SOL_SOCKET, SO_SNDBUFFORCE, &snd_buf_size, sizeof(snd_buf_size)) < 0) {
    g_info("relay: setsockopt(SO_SNDBUFFORCE) on sender failed: %s, falling back to SO_SNDBUF",
           strerror(errno));
    if (setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, &snd_buf_size, sizeof(snd_buf_size)) < 0)
        g_debug("relay: setsockopt(SO_SNDBUF) on sender failed: %s", strerror(errno));
}

在发送端(fds[0])上设置 8 MiB 发送缓冲区,与已有的接收端配置(fds[1])保持对称。使用 SO_SNDBUFFORCE 绕过 wmem_max 限制,失败时回退到 SO_SNDBUF。


审查结论

本次提交是一个高质量的 Bug 修复,代码变更目的明确(修复 relay 发送端缓冲区未增大导致慢客户端被踢的问题),实现方式正确(与已有接收端配置对称),注释详尽,错误处理完善。未发现任何安全漏洞、语法错误、质量问题或性能问题。

建议: 无需修改,可以合并。


OCR 审查结果

  • 状态: 已完成
  • 审查文件数: 1
    发现问题数: 0
  • 结论: "Looks good to me"

SAST 扫描结果

  • 状态: 不可用(无 SAST 扫描结果)

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: lzwind, wangrong1069

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@wangrong1069

Copy link
Copy Markdown
Contributor Author

/merge

@deepin-bot
deepin-bot Bot merged commit 5ea7bf6 into linuxdeepin:develop/snipe Oct 15, 2026
17 checks passed
@wangrong1069
wangrong1069 deleted the agent/pms-bug-bot/4ed5286b73e5 branch October 15, 2026 03:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants