2015-03-30 3 views
1

Мне нужно знать, если какой-то поток уже завершен (если это не так, я должен дождаться его).
Если я назову pthread_join() на завершаемой нити, он всегда возвращает успех в моей версии glibc. Но документация для pthread_join() говорит, что она должна возвращать ошибку с кодом ESRCH, если поток уже завершен.
Если я звоню pthread_kill(thread_id, 0), он возвращается с кодом ошибки ESRCH (как и ожидалось).
Внутри источников glibc Я вижу, что внутри pthread_join() существует простая проверка правильности thread_id, но не реальная проверка, существует ли поток. И внутри pthread_kill() есть реальная проверка (в некотором списке ядра). Существует моя тестовая программа:Могу ли я использовать pthread_join() для проверки завершенного потока?

#include <errno.h> 
#include <pthread.h> 
#include <signal.h> 
#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 

void * thread_func(void *arg) 
{ 
    printf("Hello! I`m thread_func!\nGood-bye!\n"); 
    return NULL; 
} 

int main(void) 
{ 
    int res; 
    pthread_t thread_id; 

    printf("Hello from main()!\n"); 
    pthread_create(&thread_id, NULL, thread_func, NULL); 
    printf("Waiting...\n"); 
    sleep(3); 

    res = pthread_join(thread_id, NULL); 
    printf("pthread_join() returned %d (%s)\n", res, strerror(res)); 

    res = pthread_kill(thread_id, 0); 
    printf("pthread_kill() returned %d (%s)\n", res, strerror(res)); 

    return 0; 
} 

Это выход:

 
    Hello! 
    Waiting... 
    Hello! I`m thread_func! 
    Good-bye! 
    pthread_join() returned 0 (Success) 
    pthread_kill() returned 3 (No such process) 

Мой вопрос: безопасно использовать pthread_join() для проверки прерванных нитей, или я должен всегда использовать pthread_kill()?

ответ

1

pthread_join завершает использование ресурсов в потоке. Он возвращает 0, когда поток достигнет конечной точки и готов к очистке. По умолчанию ни один из них не «уходит».

Возвращаясь к нулю означает:

1. the thread got cleaned up 
2. the thread WAS still there waiting 

Так что нет, не используйте pthread_kill, у вас есть основные предположения, что это неправильно: нитки, если набор не будет, не объединяемые не выйти и стек очистки и ресурсы памяти когда поток возвращается. Другими словами, return NULL в вашем примере di НЕ завершает поток. pthread_join сделал.

Итак, да, используйте pthread_join, чтобы дождаться завершения потока.

1

Когда поток выходит, код для него останавливается, но его «труп» остается лежать вокруг, так как код возврата должен быть собран родителем.

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

Звонок pthread_join будет проверять указанный труп на код возврата, чтобы родитель был уведомлен о том, как все получилось. После того, как, который был собран, нить может быть действительно положена на отдых.

Это почему pthread_join() возвращается код успеха и pthread_kill нет - это не позволено убивать поток, который уже мертв, но pthread_joinэто разрешено присоединиться к одному, что мертв, но еще тепло: -)

Вы можете быть более образованными, пытаясь следующий код, который пытается присоединиться к теме дважды:

#include <errno.h> 
#include <pthread.h> 
#include <signal.h> 
#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 

void * thread_func(void *arg) 
{ 
    printf("Hello! I`m thread_func!\nGood-bye!\n"); 
    return NULL; 
} 

int main(void) 
{ 
    int res; 
    pthread_t thread_id; 

    printf("Hello from main()!\n"); 
    pthread_create(&thread_id, NULL, thread_func, NULL); 
    printf("Waiting...\n"); 
    sleep(3); 

    res = pthread_join(thread_id, NULL); 
    printf("pthread_join() returned %d (%s)\n", res, strerror(errno)); 

    res = pthread_join(thread_id, NULL); 
    printf("pthread_join() returned %d (%s)\n", res, strerror(errno)); 

    return 0; 
} 

В моей системе я вижу:

Hello from main()! 
Waiting... 
Hello! I`m thread_func! 
Good-bye! 
pthread_join() returned 0 (No error) 
pthread_join() returned 3 (No error) 

Другими словами, хотя поток мертв, первые pthread_join() работы.


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

pthread_create(&thread_id, NULL, thread_func, NULL); 
pthread_detach(thread_id); 

, но я вполне уверен, то присоединиться к потерпит неудачу в этом случае, даже если поток все еще жив.

Чтобы увидеть, если поток еще работает независимо от того, является ли он отдельно или нет, вы можете просто использовать:

if (pthread_kill(thread_id, 0) != 0) 
    // Thread is gone. 

Извинения для нездоровых тона этого ответа, «м, кажется, немного темно сегодня :-)

+0

Спасибо за ваш ответ, но мой' человек 3 pthread_join' говорит: „Соединение с резьбой, который ранее был присоединен результаты к неопределенному поведению“. – Zhenya4880

+0

@ Zhenya4880, я не говорю, что вы должны сделать это в производственном коде, это была иллюстрация, указывающая на то, что поток не исчезнет полностью, пока вы не соберете код возврата. Если вы хотите получить сообщение об ошибке из первого соединения, отделите поток при его создании - я добавлю еще один код. – paxdiablo

+0

Нет, спасибо. Я понял. – Zhenya4880

Смежные вопросы