在 C++17 中,是否未定义使用无锁原子学保护从信号处理程序传递的数据?
In C++17, is it undefined to protect data passed from a signal handler using lock-free atomics?
根据我对过去问题的解读,该标准允许在信号处理程序中访问无锁原子,并且对"普通"对象的任何修改都变得未定义。如果是这样,以下模式(其中原子变量是非原子变量的内存屏障(是否也未定义?
下面的模式是单一生产者-签名-消费者环形缓冲区的模式。信号是生产者,线程是消费者。请忽略正在旋转的收集线程中的低效率 - 不想使已经复杂的示例复杂化。
AFAICT,这种模式在信号处理程序中使用是安全的,因为原子变量可以防止任何竞赛,并且我避免在信号处理程序内部分配内存。但是,它确实修改了信号处理程序中的非原子对象。
vector<vector<int>> ring;
atomic<int> push_idx;
atomic<int> pop_idx;
void init()
{
ring.resize(8);
for (auto &v : ring)
{
v.resize(10);
}
}
int advance_idx(int i)
{
return (i + 1) % 8;
}
int buf[5];
void sig_handler()
{
int a = push_idx.load(memory_order_relaxed);
int p = pop_idx.load(memory_order_acquire);
if (advance_idx(a) == p)
{
return; // ring overflow
}
// fill up static-linkage data
for (int i = 0; i < 5; i++)
{
buf[i] = i;
}
// copy some static-linkage data into buffer
for (int i = 0; i < 5; i++)
{
ring[a][i] = buf[i];
}
ring[a].resize(5);
push_idx.store(advance_idx(a), memory_order_release)
}
void collecting_thread()
{
for (;;)
{
int p = pop_idx.load(memory_order_relaxed);
int a = push_idx.load(memory_order_acquire);
if (p == a)
{
continue; // nothing to do
}
auto &vec_to_process = ring[p];
process_vec(std::move(vec_to_process); //may move-from
vec_to_process.clear();
vec_to_process.resize(10);
pop_idx.store(advance_idx(p), memory_order_release);
}
}
根据评论回答我自己的问题 - 这似乎是未定义的行为,一如既往。
正如在sem_post、信号处理程序和未定义行为(关于 POSIX 的(的答案中所说,它未定义不是因为它与信号、线程、原子组学或 CPU 的工作方式相矛盾,而是因为指定正确的行为很困难,没有显着的收益。
在大多数情况下,处理信号的正确做法是在信号处理程序中设置一个标志,或者"接受信号"(sigwait(( et. al(。就我而言,这不起作用,因为我需要获取堆栈跟踪(SIGPROF处理程序(并将其交付给应用程序。
相关文章:
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 有可能在信号处理程序中设置promise吗
- 在信号处理程序中捕获C++未处理的异常并恢复应用程序
- 通过安装信号处理程序关闭多线程应用程序
- 为什么我的信号处理程序只执行一次?
- GTK C++:找不到信号处理程序 您是否使用 -rdynamic 进行了编译?
- C++ 在信号处理程序后继续执行
- 没有信号处理程序的POSIX定时器的目的是什么?
- 为什么这个信号处理程序不能捕获 SIGHUP 或 SIGQUIT?
- 如何在C++中使用 std::bind 函数作为信号处理程序?
- 在 C++17 中,是否未定义使用无锁原子学保护从信号处理程序传递的数据?
- 如何将信号处理程序添加为方法
- 窗口上信号处理程序的异步安全写入函数
- 使用信号处理程序处理从 FIFO 接收的数据
- gtkmm/glade - 将信号处理程序连接到 MenuShell
- GTK+3 编译错误"找不到信号处理程序",您是否使用 -rdynamic 进行了编译?
- Linux 中的信号处理程序使用 sigaction (C++)
- 使用 enum 参数将 C++ 对象信号连接到 QML 信号处理程序
- 信号处理程序不要求使用dlopen或dlclose