Как вы запрашиваете pthread, чтобы узнать, все ли работает?
В моем деструкторе я хочу уничтожить поток чисто.
Моя цель - дождаться завершения потока и THEN уничтожить поток.
Единственное, что я нашел о запросе состояния pthread: pthread_attr_setdetachstate, но это только говорит вам, есть ли ваш поток:
- PTHREAD_CREATE_DETACHED
- PTHREAD_CREATE_JOINABLE
Оба из них не имеют никакого отношения к тому, продолжает ли поток работать или нет.
Как вы запрашиваете pthread, чтобы проверить, все ли работает?
Ответы
Ответ 1
Похоже, у вас есть два вопроса:
Как я могу дождаться завершения моего потока?
Ответ: Это напрямую поддерживается pthreads - сделайте свой поток для остановки JOINABLE (при первом запуске) и используйте pthread_join(), чтобы заблокировать текущий поток до тех пор, пока поток не будет остановлен больше не работает.
Как узнать, работает ли мой поток?
Ответ: вы можете добавить флаг "thread_complete" , чтобы сделать трюк:
Сценарий: Thread A хочет узнать, жив ли поток B.
Когда создается поток B, ему присваивается указатель на адрес флага "thread_complete" . Флаг "thread_complete" должен быть инициализирован до NOT_COMPLETED до создания потока. Функция точки входа B должна немедленно вызвать pthread_cleanup_push(), чтобы нажать "обработчик очистки", который устанавливает флаг "thread_complete" в COMPLETED.
Подробнее о обработчиках очистки см. здесь: обработчики очистки pthread
Вы хотите включить соответствующий вызов pthread_cleanup_pop (1), чтобы гарантировать, что обработчик очистки будет вызван независимо от того, что (например, если поток выходит из строя ИЛИ из-за отмены и т.д.).
Затем Thread A может просто проверить флаг "thread_complete" , чтобы узнать, еще ли вышел поток B.
ПРИМЕЧАНИЕ. Ваш флаг "thread_complete" должен быть объявлен "изменчивым" и должен быть атомным типом - компиляторы GNU предоставляют sig_atomic_t для этой цели. Это позволяет двум потокам согласовывать одни и те же данные без необходимости в конструкциях синхронизации (мьютексы/семафоры).
Ответ 2
pthread_kill(tid, 0);
Сигнал не отправляется, но проверка ошибок по-прежнему выполняется, поэтому вы можете использовать это для проверки
существование tid.
ПРЕДОСТЕРЕЖЕНИЕ. Этот ответ неверен. В стандарте конкретно запрещается передавать идентификатор потока, срок службы которого закончился. Этот идентификатор теперь может указывать другой поток или, что еще хуже, он может ссылаться на освобожденную память, вызывая сбой.
Ответ 3
Я думаю, что вам действительно нужно называть pthread_join(). Этот вызов не вернется, пока поток не выйдет.
Если вы хотите только опросить, будет ли поток по-прежнему работать или нет (и обратите внимание, что обычно это не то, что вам нужно делать!), вы могли бы установить, что поток установил volatile boolean в false до него выходы... тогда ваш основной поток мог бы прочитать логическое значение, и если это все еще верно, вы знаете, что поток все еще работает. (если это ложь, с другой стороны, вы знаете, что поток, по крайней мере, почти ушел, он все равно может работать с кодом очистки, который возникает после того, как он устанавливает логическое значение в false, хотя, поэтому даже в этом случае вам все равно нужно вызвать pthread_join раньше пытаясь освободить любые ресурсы, к которым может иметь поток)
Ответ 4
Нет полностью портативного решения, посмотрите, поддерживает ли ваша платформа pthread_tryjoin_np или pthread_timedjoin_np. Поэтому вы просто проверяете, может ли поток быть соединен (конечно, созданный с помощью PTHREAD_CREATE_JOINABLE).
Ответ 5
Позвольте мне отметить "выигрышный" ответ, который имеет огромный скрытый недостаток, и в некоторых контекстах это может привести к сбоям. Если вы не используете pthread_join, он будет появляться снова и снова. Предположим, что у вас есть процесс и общая библиотека. Вызвать библиотеку lib.so.
- Вы затормозите его, вы начинаете в нем нить. Предположим, вы не хотите, чтобы он присоединился к нему, поэтому вы установите его съемным.
- Процесс и общая логика lib выполняют свою работу и т.д.
- Вы хотите загрузить lib.so, потому что вам это больше не нужно.
- Вы вызываете выключение по потоку, и вы говорите, что вы хотите прочитать флаг из потока lib.so, который он завершил.
- Вы продолжаете использовать другой поток с dlclose, потому что видите, что вы видели, что флаг теперь показывает поток как "законченный"
- dlclose будет загружать всю стек и связанную с кодом память.
- Хвосты, но dlclose не останавливает потоки. И вы знаете, даже когда вы находитесь в последней строке обработчика очистки, чтобы установить "поток завершен" изменчивой переменной атомного флага, вам все равно придется возвращаться из множества методов в стеке, возвращая значения и т.д. Если приоритет огромного потока был задан для потока # 5 + # 6, вы получите dlclose, прежде чем сможете ДЕЙСТВИТЕЛЬНО остановиться на потоке. Иногда у вас будут приятные сбои.
Позвольте мне отметить, что это не проблема, я имел ту же проблему в нашем проекте.
Ответ 6
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
void* thread1 (void* arg);
void* thread2 (void* arg);
int main()
{
pthread_t thr_id;
pthread_create(&thr_id, NULL, thread1, NULL);
sleep(10);
}
void* thread1 (void* arg)
{
pthread_t thr_id = 0;
pthread_create(&thr_id, NULL, thread2, NULL);
sleep(5);
int ret = 0;
if( (ret = pthread_kill(thr_id, 0)) == 0)
{
printf("still running\n");
pthread_join(thr_id, NULL);
}
else
{
printf("RIP Thread = %d\n",ret);
}
}
void* thread2 (void* arg)
{
// sleep(5);
printf("I am done\n");
}