从信号处理程序设置变量时是否需要 std::atomic 或 volatile

问题描述 投票:0回答:1
#include <unistd.h>

#include <csignal>
#include <exception>
#include <functional>
#include <iostream>

std::function<void(int)> g_signalHandler;

void signalWrapper(const int a) { g_signalHandler(a); }

int main() {
    bool abort = false;
    g_signalHandler = [&abort](const int) {
        std::cout << "Abort" << std::endl;
        abort = true;
    };

    struct ::sigaction signalAction = {};
    signalAction.sa_handler = signalWrapper;

    if (
        ::sigaction(SIGHUP,  &signalAction, nullptr) != 0 ||
        ::sigaction(SIGINT,  &signalAction, nullptr) != 0 ||
        ::sigaction(SIGTERM, &signalAction, nullptr) != 0
    )
        throw std::exception();

    // Is it guaranteed that the new value of abort will be seen here without
    // the need of std::atomic<bool> or volatile bool?
    while (!abort)
        ::sleep(1);

    return 0;
}

假设单线程程序、C++17 和 Linux

据我所知,使用普通的

bool
对于
while (!abort)
来说就足够了,而
std::atomic<bool>
/
volatile bool
则没有必要。我想确认这始终是正确的,并且我不必担心编译器优化读取值

c++ c++17 signals
1个回答
0
投票

据我所知,使用普通 bool 足以满足 while (!abort) 的要求,而 std::atomic / volatile bool 则没有必要。我想确认这始终是正确的,并且我不必担心编译器优化读取值

不,这是错误的,会导致数据竞争,这始终是未定义的行为。

您保证能够通过信号处理程序中定义的行为访问的唯一非局部变量是

  • volatile std::atomic_sig_t
    类型的对象(通过
    volatile
    泛左值访问);仅当信号处理程序和运行信号处理程序的线程之间独占共享(没有其他同步)时,没有其他线程
  • 任何无锁原子对象;
    std::atomic_flag
    保证无锁;哪些
    std::atomic
    专业是无锁的,取决于平台,可以通过
    is_lock_free
    is_always_lock_free
    成员进行检查。
© www.soinside.com 2019 - 2024. All rights reserved.