Что делать с std::thread после того, как его убили?

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

void run(void)
{
    some_resource global_resource;
    global_resource.create();

    vector<thread> my_threads;
    my_threads.reserve(thread_count);

    for(int i = 0; i < thread_count; i++)
        my_threads.push_back(
            thread([&global_resource](int i)
            {
                another_resource local_resource;
                local_resource.create();

                // SIGTERM can happen here:
                work_with_resources(global_resource, local_resource, i);

                local_resource.destroy();
            },
            i)
        );

    for(int i = 0; i < thread_count; i++)
        my_threads[i].join();

    global_resource.destroy();
}

Теперь предположим, что один из потоков, к сожалению, получил SIGTERM во время work_with_resources(). Это означает, что локальный ресурс потока никогда не будет уничтожен.

Вопрос 1: Что делать, чтобы отслеживать ресурсы? Можно ли уничтожить локальный ресурс убитого потока?

Вопрос 2: Можно ли присоединиться к потоку после его уничтожения? Будет ли метод join() возвращаться немедленно? Является ли объединение () с убитым потоком хорошей практикой?

Вопрос 3. Поскольку убитый поток мог использовать глобальный ресурс, он может остаться в недопустимом состоянии. Есть ли способ запретить всем другим потокам использовать глобальный ресурс, чтобы предотвратить дальнейший ущерб?

Библиотека потоков C++ вообще взаимодействует с сигналами?


person haael    schedule 15.02.2018    source источник
comment
Вы можете обрабатывать и игнорировать SIGTERM, но почему это происходит? Вы специально закрываете свои темы?   -  person Baum mit Augen    schedule 15.02.2018
comment
Я пытался сделать это один раз; это было ужасно. Думаю, я (в конце концов) решил не заморачиваться.   -  person Lightness Races in Orbit    schedule 15.02.2018
comment
SIGTERM обычно уничтожает процесс, а не только один из его потоков.   -  person Jesper Juhl    schedule 15.02.2018
comment
В соответствии с этим ответом вы не можете отправить сигнал уничтожения отдельному потоку из другого процесса. Так что это никогда не должно всплывать: unix.stackexchange.com/questions/1066/   -  person Galik    schedule 15.02.2018


Ответы (1)


Во-первых, SIGTERM по-разному ведет себя с разными версиями библиотеки POSIX. В версии 2.6 SIGTERM принудительно завершит поток. Но с 2.4 поток будет в неопределенном состоянии.

Теперь ваш первый вопрос: -

Вопрос 1: Что делать, чтобы отслеживать ресурсы? Можно ли уничтожить локальный ресурс убитого потока?

В этом случае у вас нет возможности отслеживать ресурсы, и вы больше не можете получить доступ к потоку.

Теперь ваш второй вопрос: -

Вопрос 2: Можно ли присоединиться к потоку после его уничтожения? Будет ли метод join() возвращаться немедленно? Является ли объединение () с убитым потоком хорошей практикой?

Просто нет на все ваши вопросы.

Теперь ваш третий вопрос: -

Вопрос 3. Поскольку убитый поток мог использовать глобальный ресурс, он может остаться в недопустимом состоянии. Есть ли способ запретить всем другим потокам использовать глобальный ресурс, чтобы предотвратить дальнейший ущерб?

В этом случае вы можете использовать условную переменную pthread (pthread_cond_t).

person Abhijit Pritam Dutta    schedule 15.02.2018