Допустимо ли вызывать pthread_join в основном потоке? - PullRequest
7 голосов
/ 19 ноября 2010

Хорошо ли определено поведение этого кода?

#include <stdio.h>
#include <pthread.h>

pthread_t mt;

void *start(void *x)
{
    void *y;
    pthread_join(mt, &y);
    printf("joined main thread\n");
    return 0;
}

int main()
{
    pthread_t t;
    mt = pthread_self();
    pthread_create(&t, 0, start, 0);
    pthread_exit(0);
}

Ответы [ 3 ]

8 голосов
/ 19 ноября 2010

Да, это возможно. Действительно, эта возможность является одной из основных причин, по которой существует pthread_detach(). Из документов POSIX для pthread_detach() (см. man pthread_detach):

   It  has  been suggested that a "detach" function is not necessary; the
   detachstate thread creation attribute is sufficient,  since  a  thread
   need  never  be dynamically detached. However, need arises in at least
   two cases:

    1. In a cancellation handler for a pthread_join() it is nearly essen-
       tial  to  have  a pthread_detach() function in order to detach the
       thread on which pthread_join() was waiting. Without it,  it  would
       be  necessary  to  have  the  handler do another pthread_join() to
       attempt to detach the thread, which would both delay the cancella-
       tion  processing  for an unbounded period and introduce a new call
       to pthread_join(), which might itself need a cancellation handler.
       A dynamic detach is nearly essential in this case.


    2. In  order  to  detach the "initial thread" (as may be desirable in
       processes that set up server threads).

Так что то, что вы предлагаете, хорошо в соответствии со стандартами.

Редактировать: Просто чтобы подтвердить это, описание POSIX exec() гласит:

Начальная нить в новом процессе изображение должно быть присоединяемым, как если бы оно было создано с атрибутом detachstate, установленным в PTHREAD_CREATE_JOINABLE.

0 голосов
/ 20 ноября 2010

Ваш подход выглядит формально действительным для меня, в частности, поскольку вы делаете pthread_exit в конце main.

С другой стороны, я не нашел никаких указаний в POSIX, будь то илине начальная нить main должна быть присоединяемой или нет.Обоснование в ответе psmears только требует, чтобы main был отсоединяемым, если он создан для объединения.

Также что-то еще злонамеренное может вызвать pthread_detach из подпрограммы, вызванной main или около того.Таким образом, вы должны окончательно проверить возвращаемое значение pthread_join, чтобы проверить наличие такого случая.

Также в вашем примере кода вы имеете гонку между созданием start и завершением main:

  • main может быть прерван до того, как start достигнет pthread_join

Мьютексирование доступа к переменной mt должно это зафиксировать.

0 голосов
/ 19 ноября 2010

Я не могу представить, почему вы сделали бы это в реальном приложении (кто-то, пожалуйста, прокомментируйте пример, если вы можете придумать один), но я не верю, что это даже возможно.Во всех поисках pthread, на которые я смотрел, соединение всегда вызывается из основного потока, а не из вторичного потока.

Для объединения также требуется, чтобы поток, к которому вы пытаетесь присоединиться, был создан с помощью PTHREAD_CREATE_JOINABLEфлаг.У меня не было возможности найти какую-либо документацию, подтверждающую, создан ли основной поток как таковой.

У Codeguru есть похожий вопрос здесь , который может помочь, а может и не помочь прояснить его..

Если вы хотите, чтобы дочерний поток продолжал работу после выхода из основного потока, вы должны создать дочерний поток отдельно или использовать вместо него fork / vfork, в зависимости от того, на какой платформе вы работаете.включен.

...