Skip to content

fix(epoll): 正确处理普通文件的epoll事件#1528

Merged
fslongjin merged 1 commit intoDragonOS-Community:masterfrom
fslongjin:fix-sys-select
Dec 21, 2025
Merged

fix(epoll): 正确处理普通文件的epoll事件#1528
fslongjin merged 1 commit intoDragonOS-Community:masterfrom
fslongjin:fix-sys-select

Conversation

@fslongjin
Copy link
Member

  • 修复普通文件在epoll中总是就绪的逻辑,避免添加epitem
  • 改进poll_select_finish函数以支持更多时间类型
  • 修复select系统调用中timeout负值检查

- 修复普通文件在epoll中总是就绪的逻辑,避免添加epitem
- 改进poll_select_finish函数以支持更多时间类型
- 修复select系统调用中timeout负值检查

Signed-off-by: longjin <longjin@DragonOS.org>
@github-actions github-actions bot added the Bug fix A bug is fixed in this pull request label Dec 21, 2025
@fslongjin
Copy link
Member Author

@claude review this PR in Chinese

@dragonos-community-ai-pr-reviewer
Copy link

dragonos-community-ai-pr-reviewer bot commented Dec 21, 2025

Claude finished @fslongjin's task in 4m 55s —— View job


PR审查:fix(epoll): 正确处理普通文件的epoll事件

待办事项列表:

  • 创建GitHub评论待办事项列表
  • 分析PR修改的文件内容
  • 审查event_poll.rs的修改
  • 审查poll.rs的修改
  • 审查sys_select.rs的修改
  • 提供中文代码审查反馈

总体评价:
这个PR解决了epoll处理普通文件的重要问题,改进合理且必要。代码质量良好,符合Linux epoll的语义。以下是对各个修改的详细审查:


1. kernel/src/filesystem/epoll/event_poll.rs (+42/-5)

主要修改:

  1. 修复close函数中的错误处理 (event_poll.rs:91):

    // 尝试移除epitem,忽略错误(对于普通文件,我们没有添加epitem,所以会失败)
    let _ = file.remove_epitem(epitm);
    • 优点:正确处理了普通文件没有epitem的情况,避免不必要的错误传播。
    • 建议:无。
  2. 增强ep_insert函数对普通文件的处理

    • 添加文件类型检查(FileType::File | FileType::Dir

    • 扩展poll错误检查,包含ENOSYSEOPNOTSUPP_OR_ENOTSUP

    • 对于普通文件且不支持poll的情况:

      • 视为总是就绪(返回EPOLLIN | EPOLLOUT | EPOLLRDNORM | EPOLLWRNORM
      • 不添加epitem到文件(因为它们不需要事件通知)
    • 优点

      • 符合Linux行为:普通文件和目录不会阻塞,总是可读/可写
      • 避免为普通文件添加不必要的epitem,减少开销
      • 错误检查更全面
    • 潜在问题:第630行的条件if is_always_ready_file && poll_not_supported可能过于严格。如果普通文件意外支持poll(例如通过某些驱动),这个逻辑可能跳过添加epitem,但考虑到普通文件确实不应该支持poll,这可能是安全的。

  3. 代码质量

    • 注释清晰,解释了"总是就绪"的逻辑
    • 错误处理合理
    • 符合Rust惯用写法

2. kernel/src/filesystem/poll.rs (+29/-5)

主要修改:

  1. 公开poll_select_finish函数和PollTimeType枚举

    • fn poll_select_finish改为pub fn poll_select_finish

    • enum PollTimeType改为pub enum PollTimeType

    • 优点:使这些类型可被sys_select.rs使用,代码复用性好。

  2. 扩展poll_select_finish支持的时间类型

    • 新增对TimeValOldTimeValOldTimeSpec的处理

    • 移除todo!(),实现完整功能

    • 使用buffer_protected()?.write_one()替代copy_one_to_user()

    • 优点

      • 功能完整,支持所有时间类型
      • 写用户空间的方式更符合当前API
    • 注意点:第207行if end_time.total_millis() <= 0中的total_millis()方法需要确保end_time不小于当前时间。在正常调用流程中这应该成立。


3. kernel/src/filesystem/vfs/syscall/sys_select.rs (+12/-6)

主要修改:

  1. 增加timeout负值检查

    if ts.tv_sec < 0 || ts.tv_usec < 0 {
        return Err(SystemError::EINVAL);
    }
    • 优点:符合POSIX规范,负的timeout值应返回EINVAL
  2. 使用poll_select_finish统一处理剩余时间

    • 变量名从timeout改为end_time更清晰

    • 调用poll_select_finish更新用户空间timeout

    • 优点:代码复用,逻辑清晰,与poll/ppoll行为一致。


建议改进点:

  1. 边界条件考虑 (event_poll.rs:630):

    if is_always_ready_file && poll_not_supported {
        return Ok(());
    }
    • 考虑添加一条日志或注释,说明为普通文件跳过了epitem添加,便于调试。
  2. 错误处理一致性

    • poll_select_finish中第222、236、248行的错误处理都是静默返回原结果。这符合Linux行为,但可考虑添加trace日志。
  3. 测试建议

    • 添加针对普通文件epoll的测试用例
    • 测试负值timeout的select调用
    • 验证各种时间类型的poll_select_finish行为

CI状态:

✅ 所有CI检查通过:


总结:

这是一个高质量的修复PR,解决了epoll处理普通文件的核心问题,并改进了相关基础设施。修改符合Linux内核行为,代码清晰可维护。建议合并。

推荐动作:✅ 批准合并


审查完成时间:2025-12-21

@fslongjin fslongjin merged commit 03b8928 into DragonOS-Community:master Dec 21, 2025
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug fix A bug is fixed in this pull request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant