Linux 计时器挂起信号
Linux timer pending signal
我正在使用带有SIGEV_THREAD参数的timer_create创建 linux 计时器。
有时在我撤防计时器并删除它后会调用回调。这会导致段错误,因为它尝试访问已删除的资源。
http://man7.org/linux/man-pages/man2/timer_delete.2.html
Linux手册说
timer_delete() 删除 ID 在 timerid 中给出的计时器。 如果 计时器在此呼叫时已武装,之前已解除武装 被删除。处理由 未指定已删除的计时器。
这基本上意味着我真的不知道是否会调用回调,在清理资源之前,我既没有办法取消它,也没有办法强制挂起的信号传递。
class timer_wrapper
{
private:
std::function<void()> callback_;
timer_t timer_;
static void timer_callback(sigval_t val)
{
static_cast<timer_wrapper*>(val.sival_ptr)->callback_();
}
public:
timer_wrapper(std::function<void()> callback, uint32_t interval_sec)
: callback_(std::move(callback))
{
struct sigevent ev;
ev.sigev_notify = SIGEV_THREAD;
ev.sigev_signo = 0;
ev.sigev_value.sival_ptr = this;
ev.sigev_notify_function = &timer_wrapper::timer_callback;
ev.sigev_notify_attributes = 0;
timer_create(CLOCK_REALTIME, &ev, &timer_);
struct itimerspec spec = {{0, 0}, {interval_sec, 0}};
timer_settime(timer_, 0, &spec, nullptr);
}
~timer_wrapper()
{
timer_delete(timer_);
}
};
如果timer_wrapper超出范围,我希望回调不会再被调用,但是有时会调用它,根据人的说法,这是预期的行为。
解决此问题的建议方法是什么?
删除使用timer_create()
创建的计时器时,避免计时器生成的事件的最简单方法是根本不避免它。相反,请使用volatile sig_atomic_t disarmed = 0;
标志,并让事件函数在执行任何其他操作之前测试该标志,如果disarmed
为非零,则立即返回。
这样,您首先设置disarmed
,然后删除计时器。
(最好使用原子内置,要么是旧式__sync_fetch_and_add(&disarmed, 0)
和__sync_fetch_and_and(&disarmed, 0)
,要么是__atomic_load_n(&disarmed, __ATOMIC_SEQ_CST)
和__atomic_exchange_n(&disarmed, 0, __ATOMIC_SEQ_CST)
,来访问标志,以确保正确的排序。
对于SIGEV_SIGNAL
,您可以先(使用pthread_sigmask()
)阻止信号,删除计时器,使用零超时sigtimedwait()
检查在计时器删除期间是否发出信号,最后恢复旧的信号掩码。
(我个人使用单个 POSIX 实时信号(SIGRTMIN+0
到SIGRTMAX-0
,在编译时定义),以及一个以事件时间为键的最小堆(每个堆槽包含时间和对自定义超时/事件结构的引用),使用专用线程处理大量事件。
- 挂起和取消挂起一个文件DLL
- 如何防止C++遗留代码中的挂起指针
- 为什么所有C++编译器都会崩溃或挂起此代码
- 我编写了代码将十进制分数转换为其二进制等效数.它编译得很好,但在执行时挂起
- 构建挂起,即使是适度的文件大小
- 循环挂起迭代的 std::擦除 on std::list
- Poco::Net::FTPClientSession 在 open() 方法上挂起 129 秒,如果 ftp 主机不存
- Node.js fs.open() 在尝试打开 4 个以上的命名管道 (FIFO) 后挂起
- 从不同进程中的另一个线程挂起/恢复线程或进程
- Boost (Beast) websocket:同步写入挂起
- 为什么析构函数挂起
- 使用互斥会挂起程序
- 在C++和 Python 程序中使用命名管道的 IPC 挂起
- 设置变量时C++程序挂起
- 第一次尝试使用new动态创建结构数组,程序挂起没有错误
- 从stdin读取时子进程挂起(fork/dup2竞争条件)
- 有时ShowWindow从不调用OnShowWindow,主应用程序挂起
- 程序在没有操作系统信号的情况下在函数中的特定行挂起
- Linux 计时器挂起信号
- MFC应用程序挂起在发出终止信号的线程中