Запрос к pthread_join()

Ниже приведена программа, для которой я ожидаю, что программа зайдет в тупик, потому что pthread_join() - это блокирующее ожидание в потоке (ожидание завершения).

Но я вижу, что pthread_join() не блокируется и возвращается с ошибкой (35)

Можете ли вы помочь мне понять, почему pthread_join() разблокируется? Потому что основной поток еще не завершен, и, вероятно, это должно быть тупиком?

#include <pthread.h>

int
main(int argc, char *argv[])
{

    void *res;
    int s;
    printf("Message from main()\n");

    s = pthread_join(pthread_self(), &res);
    if (s != 0)
        printf("pthread_join(): %d",s);

    printf("Thread returned %d\n", (int) res);
    exit(0);
}

Вот результат:

Message from main()
pthread_join(): 35
Thread returned 134514009

person overexchange    schedule 07.06.2014    source источник
comment
это упражнение входит в мою программу   -  person overexchange    schedule 07.06.2014
comment
Вместо printf("pthread_join(): %d",s); сделайте {errno = s; perror("pthread_join()");}, и вы можете получить поучительную информацию.   -  person alk    schedule 07.06.2014


Ответы (1)


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

[EDEADLK]
    A deadlock was detected or the value of thread specifies the calling thread.

И действительно, поиск этой ошибки показывает, что это 35, по крайней мере, в моей системе:

pax> cd /usr/include
pax> grep EDEADLK *.h */*.h */*/*.h
asm-generic/errno.h:#define EDEADLK     35  /* Resource deadlock would occur */

В то время как некоторые тупиковые ситуации неуловимы и их трудно автоматически обнаружить pthreads, это относительно легко, с чем-то вроде этого в начале функции соединения:

int pthread_join(pthread_t thread, void **value_ptr) {
    if (thread == pthread_self())
        return EDEADLK;
    // rest of function
}
person paxdiablo    schedule 07.06.2014
comment
Можно добавить, что значение res (адрес которого был передан pthread_join()) не содержит значимых данных, если pthread_join() не удалось. Более того, в этом случае сбоя, если res не был инициализирован до его использования с pthread_join() (согласно фрагменту кода OP), распечатка его значения вызывает неопределенное поведение. - person alk; 07.06.2014
comment
Согласно моему запросу, я чувствовал, что это тупик. Вы говорите, что pthread_join() достаточно умен, чтобы обнаружить взаимоблокировку и выйти из нее? Это причина, по которой я могу видеть заявление «Поток возвращен»? - person overexchange; 07.06.2014
comment
@overexchange: да, в документации четко указано, что EDEADLK является одной из возможных ошибок, если значение thread указывает вызывающий поток. Учитывая, что EDEADLK равен 35 (в моей системе и, вероятно, также и в вашей) и это то, что вы получили, ваша реализация обнаруживает этот сценарий взаимоблокировки. Это может быть легко поймано в соединении с чем-то вроде if (passed_thread == pthread_self()) return EDEADLK;. Добавлю к ответу. - person paxdiablo; 07.06.2014
comment
@paxdiablo еще один вопрос, я вижу много примеров, где 'pthread_join(t1,NULL);' используется. Как я должен понимать передачу NULL в pthread_join(). Означает ли это, что pthread_join() не ждет завершения потока? или Ожидает ли pthread_join() завершения потока, но не фиксирует возвращаемое значение? - person overexchange; 09.06.2014
comment
@overexchange: это последнее. Он по-прежнему ожидает завершения потока, но, поскольку вы нигде не указываете место для сохранения значения выхода, он отбрасывается. - person paxdiablo; 09.06.2014