Блоки переменных условий в главном потоке - PullRequest
0 голосов
/ 03 марта 2019

Я хочу использовать условные переменные для запуска не более N потоков, чтобы обработать все файлы одним огромным каталогом (1 М файлов).

Код работает, но через некоторое время блокируется в главном потоке.Ниже код разочарования:

void* run(void* ctx)
{
    clientCtx* client = (clientCtx*)ctx;
    printf("New file from thread %d: %s\n", client->num, client->filename);
    free(client->filename);
    pthread_mutex_lock(&clientFreeMutex);
    client->state = IDLE_STATE;
    pthread_cond_signal(&clientFreeCond);
    printf("Thread %d is free\n", client->num);
    pthread_mutex_unlock(&clientFreeMutex);
    return NULL;
}

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

    pthread_t client[MAX_CLIENT] = {0};
    clientCtx ctx[MAX_CLIENT] = {0};
    DIR* directory = NULL;
    struct dirent* element = NULL;

    /* Initialize condition variable for max clients */
    pthread_mutex_init(&clientFreeMutex, NULL);
    pthread_cond_init(&clientFreeCond, NULL);

    /* Initialize contexts for clients */
    for (int cnt = 0; cnt < MAX_CLIENT; cnt ++)
    {
        ctx[cnt].state = IDLE_STATE;
        ctx[cnt].num = cnt;
    }

    directory = opendir(argv[1]);

    while((element = readdir(directory)) != NULL)
    {
        pthread_mutex_lock(&clientFreeMutex);
        int cnt;
        for (cnt = 0; cnt < MAX_CLIENT; cnt++)
        {
            if(ctx[cnt].state == IDLE_STATE)
            {
                ctx[cnt].filename = strdup(element->d_name);
                ctx[cnt].state = BUSY_STATE;
                pthread_create(&client[cnt], NULL, run, &(ctx[cnt]));
                break;
            }
        }
        /* No free client */
        if (cnt == MAX_CLIENT)
        {
            printf("No free thread. Waiting.\n");
            pthread_cond_wait(&clientFreeCond, &clientFreeMutex);
        }
        pthread_mutex_unlock(&clientFreeMutex);
    }
    closedir(directory);
    exit(EXIT_SUCCESS);
}

В чем проблема?спасибо за вашу помощь :)

Ответы [ 2 ]

0 голосов
/ 03 марта 2019

Я наконец обнаружил проблему: запущенные потоки не были объединены, и pthread_create наконец вернул код ошибки с сообщением errno, установленным на «Не удалось выделить память».Сигнал никогда не отправлялся, и основной поток затем блокировался.

Я исправил это, создав новое состояние для уже запущенных потоков и добавив соединение в основной цикл.

0 голосов
/ 03 марта 2019

Предупреждение: вы используете значение readdir в отдельных потоках без какой-либо защиты от многопоточности, поэтому, когда вы (пытаетесь) printf client->file->d_name, возможно, вы это делаетев то же время readdir в главном потоке, изменяющем сохраненный результат, имеет неопределенное поведение.

Вам необходимо, например, сохранить strdup из element->file->d_nameв main и сохраните эту строку в clientCtx , а не struct dirent *, и, конечно, для ее освобождения в run

Обратите внимание также closedir отсутствует в конце main , даже в этом случае это не является реальной проблемой (просто запомните для других ваших программ).

...