Подтвердить что ты не робот

Как вы запрашиваете pthread, чтобы узнать, все ли работает?

В моем деструкторе я хочу уничтожить поток чисто.

Моя цель - дождаться завершения потока и THEN уничтожить поток.

Единственное, что я нашел о запросе состояния pthread: pthread_attr_setdetachstate, но это только говорит вам, есть ли ваш поток:

  • PTHREAD_CREATE_DETACHED
  • PTHREAD_CREATE_JOINABLE

Оба из них не имеют никакого отношения к тому, продолжает ли поток работать или нет.

Как вы запрашиваете pthread, чтобы проверить, все ли работает?

4b9b3361

Ответ 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");
}