Полезно ли вызывать pthread_sigmask в потоке, созданном std::thread?

1) Я новичок в std::thread, и я хотел бы знать, является ли это хорошей практикой для вызова pthread_sigmask() блокировать некоторые сигналы в определенном потоке, созданном std::thread,

Я не хочу, чтобы новый поток получал такие сигналы, как SIGTERM, SIGHUP и т. Д., Потому что основной процесс уже установил обработчики для этих сигналов.

Итак, это хорошая практика, чтобы позвонить pthread_sigmask() блокировать некоторые сигналы в потоке, созданном std::thread?

2) Кроме того, я считаю, что эффект pthread_sigmask(SIG_BLOCK, &mask, NULL) будет применяться только к теме, созданной с помощью

std::thread(&Log::rotate_log, this, _logfile, _max_files, _compress).detach();

и звонит rotate_log() в качестве функции запуска.

И эффект pthread_sigmask(SIG_BLOCK, &mask, NULL) не будет применяться к теме, где std::thread(&Log::rotate_log, this, _logfile, _max_files, _compress).detach() называется.

Правильно ли мое понимание?

void rotate_log (std::string logfile, uint32_t max_files, bool compress)
{
    sigset_t mask;

    sigemptyset (&mask);
    sigaddset (&mask, SIGTERM);
    sigaddset (&mask, SIGHUP);
    pthread_sigmask(SIG_BLOCK, &mask, NULL);

    // Do other stuff.
}

void Log::log (std::string message)
    {
        // Lock using mutex
        std::lock_guard<std::mutex> lck(mtx);

        _outputFile << message << std::endl;
        _outputFile.flush();
        _sequence_number++;
        _curr_file_size = _outputFile.tellp();

        if (_curr_file_size >= max_size) {
            // Code to close the file stream, rename the file, and reopen
            ...


            // Create an independent thread to compress the file since
            // it takes some time to compress huge files.
            if (!_log_compression_on)
            {
                std::thread(&Log::rotate_log, this, _logfile, _max_files, _compress).detach();
            }
        }
    }

3 ответа

Теоретически возможно, что реализация std::thread создаст поток, отличный от POSIX, даже в системе, в которой есть потоки POSIX, и pthread_sigmask не будет работать для таких тем. ( Комментарий Максима Егорушкина верен - вам действительно следует блокировать потоки в потоке, создающем поток, и разблокировать только те, которые вы хотите обработать в новом потоке, чтобы избежать условий гонки.)

Я не могу говорить о других реализациях, но крайне маловероятно, что такое случится для реализации GNU/Linux. Конечно, я не могу говорить авторитетно и для этой реализации, но там просто слишком много кода на C и C++, который предполагает отображение 1:1 между потоками пространства пользователя (будь то C, C++ или POSIX) и задачами ядра (те вещи, которые есть TID). Десять лет назад люди все еще утверждали, что возможна библиотека потоков n:m (из которых ранние реализации потоков POSIX 1: m были просто особым случаем).

Но сегодня программисты называют unshare (CLONE_FS) из потока, чтобы дать этому потоку частный текущий каталог, отдельный от всех других потоков. Они звонят setfscreatecon и ожидать, что это влияет только на вызывающий поток. Они даже вызывают системные вызовы setresuid а также setresgid напрямую, потому что они хотят избежать широковещательной рассылки setxid, которую использует glibc для распространения изменений на все потоки (то, что ядро ​​не поддерживает напрямую). Все это перестало бы работать в поточной модели n:m. Так std::thread и потоки POSIX должны будут сопоставляться с задачами ядра, применяя модель 1:1.

Кроме того, существует только один GNU TLS ABI как для C, так и для C++, и это, в свою очередь, в значительной степени требует, чтобы в системе был только один тип потока, с одним указателем потока, который используется для достижения локальных данных потока,

Вот почему это так маловероятно, что в GNU/Linux, std::thread будет когда-либо использовать что-либо кроме потоков POSIX, предоставляемых glibc.

Правильный способ - установить требуемую маску сигнала в родительском элементе перед созданием потока, а затем вернуть его в родительский. Таким образом, ваш вновь созданный поток имеет правильную маску сигналов, установленную с самого начала. (Маска сигнала наследуется от родительского потока).

Когда вы устанавливаете маску сигнала после запуска потока, появляется окно времени, в течение которого поток не имеет требуемой маски.

Если вам необходимо установить маску сигнала в многопоточной программе в системе POSIX, то pthread_sigmask это функция, которую вам нужно использовать. В стандартной библиотеке C++ нет функций для взаимодействия с масками сигналов.

Кроме того, я считаю, что эффект pthread_sigmask(SIG_BLOCK, &mask, NULL) будет применяться только к теме, созданной с помощью...

pthread_sigmask применяется к потоку, в котором был выполнен вызов, независимо от того, как был создан поток. Это не относится ни к каким другим ранее существующим потокам. В случае вашего примера, функция rotate_log в котором pthread_sigmask вызывается выполняется в потоке, созданном std::thread,

Другие вопросы по тегам