You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用epoll_pwait()时如何正确调用信号,保障定时任务正常运行?

阻塞epoll_pwait场景下的定时任务实现方案

1. 信号掩码的正确使用逻辑

你使用超时为-1的epoll_pwait会遇到无IO事件时永久阻塞的问题,搭配信号唤醒的标准操作流程如下:

  • 主程序初始化阶段、创建任何子线程之前,先调用信号掩码操作接口,将你选定的唤醒信号(通常用SIGUSR1或自定义实时信号)设置为全局屏蔽状态
  • 调用epoll_pwait时,传入的临时信号掩码需要解除该唤醒信号的屏蔽,保证只有epoll_pwait阻塞的窗口期内可以接收该信号,其余业务逻辑执行阶段信号会被挂起,不会打断正常流程
  • 唤醒信号的处理函数可以留空,信号触发会直接让epoll_pwait返回-1,同时errno置为EINTR,你只需要在epoll_pwait返回后判断该错误码,先执行1秒定时任务,再重新进入下一轮循环即可

注意:多线程场景下不要使用sigprocmask,POSIX标准明确规定sigprocmask仅适用于单线程进程,多线程环境下要改用线程安全的pthread_sigmask操作线程级信号掩码。

2. 是否需要单独启动线程发信号

这是可行方案,且实现简单、对原有业务逻辑侵入性低:

  • 单独启动一个定时线程,内部循环调用nanosleep/clock_nanosleep休眠1秒,唤醒后调用pthread_kill向主循环线程发送指定的唤醒信号即可
  • 如果你不想引入额外线程和信号逻辑,也可以改用timerfd将定时事件直接挂载到epoll实例上,完全通过IO事件驱动同时处理定时任务和网络IO任务,不需要信号相关的处理。

3. 信号掩码操作接口的线程安全性

  • sigprocmask不是线程安全的,多线程进程中调用它的行为是未定义的,绝对不能在多线程场景下使用
  • 多线程场景下替换使用的pthread_sigmask是完全线程安全的,可以在任意线程中调用修改当前线程的信号掩码。

内容的提问来源于stack exchange,提问作者Carlos Ferry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 02:27:01