Безопасно ли инициализировать функционально-статическую переменную c ++ 11 из обработчика сигналов linux? - PullRequest
2 голосов
/ 31 мая 2019

2 вопроса (ниже) о статической инициализации C ++ 11 в [1] в этом справочном коде (это полный протестированный пример программы на c ++ 11).

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>

struct Foo {
    /* complex member variables. */
};

void DoSomething(Foo *foo) {
    // Complex, but signal safe, use of foo. 
}

Foo InitFoo() {
    Foo foo;
    /* complex, but signal safe, initialization of foo */
    return foo;
}

Foo* GetFoo() {
    static Foo foo = InitFoo();   // [1]
    return &foo;
}

void Handler(int sig) {
    DoSomething(GetFoo());
}

int main() {
    // [2]

    struct sigaction act;
    memset(&act, 0, sizeof(act));
    act.sa_handler = Handler;
    sigaction(SIGINT, &act, nullptr);

    for (;;) {
        sleep(1);
        DoSomething(GetFoo());
    }
}

Вопрос1: Это гарантированно безопасно (без тупиков и т. Д.)? C ++ 11 статическая инициализация включает в себя блокировки. Что если сигнал доставляется до / после / во время первого вызова GetFoo () в main?

Вопрос2: Это гарантированно безопасно, если вызов GetFoo () вставлен в [2] до установки обработчика сигнала?

Я предполагаю, что C ++ 11 (g ++ или clang) на последних версиях GNU / Linux, хотя ответы на различные Unices также были бы интересны. (Спойлер: я думаю, что ответ 1: НЕТ и 2: ДА, но я не знаю, как это доказать.)

...