Как получить код ошибки из pthread_join

В следующем коде не удается создать присоединяемые потоки, и выводится сообщение "соединение не выполнено". Как получить больше информации о сбое и его причине?

pthread_t aThread[MAX_LENGTH];
    int errCode[MAX_LENGTH];
    char returnVal;    
for(int i = 0; i < MAX_LENGTH; i++)
    {

        if((errCode[i] = pthread_create(&aThread[i], NULL, &findMatch, &fpArgs)) != 0)
            printf("error creating thread %d\n", errCode[i]);
        if(!pthread_join(aThread[i], (void**)&returnVal))
            printf("join failed\n i is %d", i);
    }

РЕДАКТИРОВАТЬ: на самом деле присоединиться вернулся no error и я ошибся Если утверждение не должно иметь ! потому что join возвращает ненулевое число, если есть проблема, которая оценивается как true.

4 ответа

Решение

Я указал на это в комментарии, но это заслуживает усиления.

Ваш returnVal использование неправильно

pthread_join API ожидает void** это указатель на void*, В отличие от void*, void** не одинаково универсален. Это указатель определенного типа, поэтому вы должны передавать только тот же тип адреса. Тем не менее, вы все равно не используете его, поэтому я бы посоветовал вам просто передать NULL. Как написано, это неопределенное поведение. И я могу гарантировать вам sizeof(char) размер записываемого вами адреса и sizeof(void*), размер, который он ожидает иметь в наличии, не совпадает. Рассмотрим это вместо этого сейчас:

pthread_join(aThread[i], NULL);

Если вам интересно, какая польза для этого void** параметр, это место для хранения void* возвращаемое значение из вашего thread-proc. Напомним, что pthread thread-proc выглядит так:

void* thread_proc(void* args)
// ^----- this is what is stashed in the pthread_join second parameter

Ты логика для провала тестирования задом наперед

pthread_join функция возвращает 0 на успех; не на провал.


Вы на самом деле не запускаете параллельные потоки

Параллельность потоков просто означает, что ваши потоки запускаются одновременно. Но ваш нет. Вы запускаете поток, затем ждете его окончания, затем запускаете поток, затем ждете его окончания и т. Д. Это буквально не лучше (и фактически даже хуже), чем простой вызов функции. Если вы хотите, чтобы ваши потоки запускались одновременно, ваша логика должна иметь такой стиль:

pthread_t aThread[MAX_LENGTH];
int errCode[MAX_LENGTH] = {0};

for (int i = 0; i < MAX_LENGTH; i++)
{
    if((errCode[i] = pthread_create(&aThread[i], NULL, &findMatch, &fpArgs)) != 0)
        printf("error creating thread %d, error=%d\n", i, errCode[i]);
}

for (int i = 0; i < MAX_LENGTH; i++)
{
    // note the check for errCode[i], which is only non-zero 
    //  if the i'th thread failed to start
    if(errCode[i] == 0)
    {
        errCode[i] = pthread_join(aThread[i], NULL))
        if (errCode[i] != 0)
            printf("error joining thread %d, error=%d\n", i, errCode[i]);
    }
}

Когда функция завершается с ошибкой (т.е. при любом вызове pthread, код возврата, который не равен нулю), она установит errno к значению причины отказа. Есть несколько способов получить текстовое объяснение кода ошибки.

int returnval;

if((returnval = pthread_join(aThread[i], (void**)&returnVal)) != 0)
{
    printf("error joining thread: %s\n", strerror(returnval));  //1st optiop

    perror("error joining thread:");  //2nd option

    printf("error joining thread: %m\n");  //3rd option

}

(1) strerror выведет строку ошибки из значения ошибки, которое вы передаете, и это удобно для размещения в операторах printf.

(2) perror позволяет передать небольшую строку, которая сначала будет напечатана, а затем автоматически выведет описание ошибки любого значения errno установлено в. Вам не нужно явно передавать errno,

(3) есть расширение glibc для printf которые обеспечивают %m спецификатор преобразования, который действует как strerror но с немного меньшим количеством беспорядка и суеты. Это было бы наименее портативным.

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

Библиотека pthread не устанавливает переменную errno при ошибке. Вместо этого функция возвращает код ошибки. Онлайн-руководство под Linux довольно ясно описывает функции pthread (например, man pthread_join), поскольку раздел "ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ" обычно содержит что-то вроде:

ВОЗВРАТНАЯ СТОИМОСТЬ

В случае успеха pthread_join() возвращает 0; при ошибке возвращается номер ошибки.

Если вам нужно вывести ошибку с помощью таких функций, как strerror (), strerror_r() или %m printf format ( последний является расширением GLIBC), вы должны использовать код возврата отказавшей службы или обновить errno в ветви ошибки:

if ((rc = pthread_join(...)) != 0) {
  errno = rc;
  fprintf(stderr, "pthread_join(): %m\n");
 OR
  fprintf(stderr, "pthread_join(): %m\n", strerror(errno)); // rc could be used without errno
 OR
  char err_buf[128];
  errno = rc;
  fprintf(stderr, "pthread_join(): %m\n", strerror_r(errno, err_buf, sizeof(err_buf))); // rc could be used without errno

Примечания:

  • errno является потокобезопасным (он находится в локальном хранилище потока). Итак, он локален для каждого потока
  • strerror_r() и %m следует использовать в многопоточной среде, поскольку они потокобезопасны (strerror () нет)

Более конкретно:

int retVal = pthread_create(&myThread, NULL,myThreadFn, NULL);
printf("error joining thread: %d\n", retVal);

Я что-то пропустил? Возвращаемое значение сообщает вам об ошибке:

ВОЗВРАЩАЕМЫЕ ЗНАЧЕНИЯ В случае успеха функция pthread_join() вернет ноль. В противном случае будет возвращен номер ошибки, чтобы указать на ошибку.

ОШИБКИ pthread_join() завершится ошибкой, если:

 [EDEADLK]          A deadlock was detected or the value of thread speci-
                    fies the calling thread.

 [EINVAL]           The implementation has detected that the value speci-
                    fied by thread does not refer to a joinable thread.

 [ESRCH]            No thread could be found corresponding to that speci-
                    fied by the given thread ID, thread.
Другие вопросы по тегам