Полезно ли вызывать pthread_sigmask в потоке, созданном std :: thread? - PullRequest
0 голосов
/ 25 февраля 2019

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 ]

0 голосов
/ 25 февраля 2019

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

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

0 голосов
/ 25 февраля 2019

Теоретически, возможно, что реализация 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.

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

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

0 голосов
/ 25 февраля 2019

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...