Ошибки статистики в pthread (S_ISDIR не работает)

В настоящее время я пытаюсь написать программу, которая находит размер дерева каталогов, а также размер всех подкаталогов в нем, создавая поток для каждого нового подкаталога и используя этот поток для определения размера подкаталога. Это довольно простая программа, но ее действительно сложно отлаживать. У меня ТОННА проблем с тем, что S_ISDIR не работает должным образом (обычные файлы передают оператор if, и моя программа пытается изменить каталог на обычные файлы). Ниже приведен код, который у меня есть для проблемы. Я хотел бы, чтобы каждый родительский каталог ждал завершения подкаталогов, но не хочу, чтобы каждый подкаталог ждал следующего.

#define NAMESIZE 256
#define NUM_THREADS 100
#define MAX_PATH_LENGTH 500

int totalSum = 0;
pthread_mutex_t sum_mutex ;
pthread_mutex_t thread_mutex ;

void *findSize(void *p)
{
    int levelSum = 0, numberThreads = 0, i = 0;
    DIR *dir ;
    struct dirent *entry ;
    struct stat entry_stat ;
    char cwd[2049] ;
    char threads[NUM_THREADS] ;
    char paths[NUM_THREADS][MAX_PATH_LENGTH];

    char *path = (char*)p ;

    // change into the directory that was passed in
    if(chdir (p) == -1)
    {
        perror("chdir");
        exit(1);
    }

    // get current working directory
    if(!getcwd (cwd, 2049))
    {
        perror("getcwd") ;
        return;
    }

    // open the directory to get entries within it
    dir = opendir(".") ;
    if(!dir)
    {
        perror("Cannot read directory");
        return;
    }

    while((entry = readdir(dir)))
    {
        // call stat on the current entry in the directory
        if(stat (entry->d_name, &entry_stat) == -1)
        {
            perror("stat error");
        }

        // skip the . and .. directories
        if(strcmp (entry->d_name, ".") == 0)
            continue;
        if(strcmp (entry->d_name, "..") == 0)
            continue;

        // check if current entry is a directory
        if(S_ISDIR (entry_stat.st_mode))
        {
            pthread_mutex_lock(&thread_mutex) ;
            strcpy(paths[numberThreads], cwd) ;
            strcat(paths[numberThreads], "/") ;
            strcat(paths[numberThreads], entry->d_name) ;

            pthread_t temp ;

            // create new thread in threads array
            if (pthread_create(&temp, NULL, findSize, (void *)paths[numberThreads]))
            {
                fprintf("failed to create thread for directory %s\n ", paths[numberThreads]) ;
                exit(1) ;
            }

            threads[numberThreads] = temp;

            // increment the number of threads created on this level of the directory tree

            numberThreads++ ;
            pthread_mutex_unlock(&thread_mutex) ;

        }


        if(S_ISREG(entry_stat.st_mode))
        {
            pthread_mutex_lock(&sum_mutex) ;
            int fileSize = entry_stat.st_size ;
            levelSum += fileSize ;
            totalSum += fileSize ;
            pthread_mutex_unlock(&sum_mutex) ;
        }
    }

    void *status ;

    for(i = 0; i < numberThreads; i++)
    {
        pthread_join(threads[i], NULL) ;
    }

}

В основном я просто делаю pthread_create с моей функцией findSize и путем, по которому проходит пользователь. Я получаю много статистических ошибок, но не могу понять, как их исправить.


person arc    schedule 19.04.2013    source источник
comment
Я удалил все операторы печати, но мои операторы печати в моем коде показывают попытки изменить каталог на файл в подкаталоге (что невозможно, потому что я проверяю S_ISDIR)   -  person arc    schedule 20.04.2013
comment
Вам не нужен собственный MAX_PATH_LENGTH, файлы заголовков системы уже предоставляют PATH_MAX для вас.   -  person Some programmer dude    schedule 20.04.2013


Ответы (1)


Текущий каталог не является локальным для потока; это свойство процесса. Таким образом, вы в конечном итоге сделаете глупость, если каждый поток попытается chdir. Вам нужно либо построить полные пути на основе результатов readdir без использования chdir, либо использовать интерфейсы "*at" (openat, fstatat и т. д.), чтобы открыть файл относительно файлового дескриптора каталога.

person R.. GitHub STOP HELPING ICE    schedule 19.04.2013
comment
хорошо, я сейчас пытаюсь переписать свой код без chdir, я обновлю, когда что-нибудь заработает. - person arc; 20.04.2013
comment
Я все еще сталкиваюсь с проблемой opendir, пытающейся открыть обычные файлы. opendir следует вызывать только в новых потоках, которые создаются только для новых каталогов. - person arc; 20.04.2013
comment
Возможно, обновите свой вопрос описанием дерева каталогов, в котором вы его запускаете (если оно содержит личную информацию, попробуйте его на более простом образце дерева и посмотрите, сможете ли вы воспроизвести проблему). - person R.. GitHub STOP HELPING ICE; 20.04.2013