Зацикливание при рекурсивном обходе каталогов
Пишу приложение которое работает с процессами pid и pipe. Программа ищет файлы заканчивающиеся на знак "~" в каталоге + во всех подкаталогах которые есть в этом каталоге. После компиляции,запускается программа и зависает, как будто не выходит из цикла. Не понимаю в чем проблема. Компилирую через g++ на ubuntu 18.04 Постарался как можно больше добавить комментариев для разборки кода.
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <linux/unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdbool.h>
#include <sys/wait.h>
#include <vector>
struct PipeList
{
int fadr[2];
pid_t pid;
};
struct result
{
int count;
char dir[4096];
};
int GetDir()
{
std::vector<pid_t> head; //Список с номерами дочерних процессов
std::vector<struct PipeList> pipeList; //Вспомогательный список с дочерними процессами
char path[4096]="."; //Основна папка
errno = 0;
DIR *dfd; //Переменная дескриптора папки
struct result mainRes; //Основная структура с результатом
strcpy(mainRes.dir, path);
mainRes.count = 0; //Начальное количество файлов
struct stat inf; //Информация о файле/каталоге
struct dirent *dp; //Переменная дескриптора каталога
pid_t pid; //Переменная с дочерним процессом
int status; //Переменная статуса процесса
int lpipe; //Вспомогательная переменная с номером процесса
if((dfd = opendir(path)) != NULL)
{
while((dp=readdir(dfd)) != NULL)
{
//printf("\nPID - %d",getpid());
char file_name[4096]; //Название файла
char b_path[4096]; //Полный путь с название файла
strcpy(file_name, dp->d_name);
strcpy(b_path, path);
strcat(b_path, "/");
strcat(b_path, file_name);
if(stat(b_path,&inf) == 0)
{
if(S_ISREG(inf.st_mode))
{
//Обработка файла
if (b_path[strlen(b_path)-1] == '~')
{
mainRes.count++;
strcpy(mainRes.dir,path);
printf("\nПуть - %s\n",b_path);
}
}
else if(S_ISDIR(inf.st_mode)!=0 && (strcmp(file_name, ".") != 0 && strcmp(file_name, "..") != 0))
{
//Проверка на каталог
//и создание процессов
if(pipeList.size() == 0)
{
//Создание новой трубы в родительском процессе
//Запись в список с трубами
struct PipeList localStruct;
lpipe = pipe(localStruct.fadr);
pipeList.push_back(localStruct);
}
else
{
//Запись номера текущего процесса
//в последний элемент списка
//Создание нового элемента списка
//Запись в новый элемент трубы
//Запись в последний элемент списка,
//что это дочерний процесс
pipeList[pipeList.size()-1].pid = getpid();
struct PipeList localStruct;
localStruct.pid = 0;
lpipe = pipe(localStruct.fadr);
pipeList.push_back(localStruct);
}
if(lpipe == 0)
{
//Создаем дочерний процесс
pid = fork();
if(pid > 0)
{
//Это родительский процесс
//Заносим в конец списка
//номер дочернего процесса
head.push_back(pid);
}
else if(pid == 0)
{
//Это дочерний процесс
//Передача в основную переменную директории
//нового пути
//Открыть папку на чтение
//Проверка на успех
//Очистка унаследованного списка
mainRes.count = 0;
strcpy(path, b_path);
dfd = opendir(path);
if (dfd == NULL) printf("\n 125 Ошибка - %s", strerror(errno));
head.clear();
}
else if(pid == -1)
{
if(errno != 0) printf("\n 130 Ошибка - %s", strerror(errno));
}
}
else if(lpipe == -1) printf("\n 133 Ошибка - %s", strerror(errno));
}
}
else if(errno) printf("\n 136 Ошибка - %s", strerror(errno));
}
if(errno!=0) printf("\n 140 Ошибка - %s Путь - %s",strerror(errno),path);
closedir(dfd);
//Обработка дочерних процессов
pid_t s;
//printf("head.size = %zu\n",head.size());
int headsize = head.size()-1;
for(int iter=headsize; iter>=0;iter--)
{
//printf("\n Процесс - %d -",getpid());
//Проверить (возможны ошибки сегментации)
s = waitpid(head[iter], &status, 0);
if (s == -1) printf("\n 154 Ошибка - %s", strerror(errno));
else if(s >= 0)
if(!WIFEXITED(status))
{
printf("\n Status: %d ERROR: %s\n",status,strerror(errno));
}
else if (WIFSIGNALED(status))
{
printf("Process %d terninated with term signal\n",pipeList[pipeList.size()-1].pid);
}
else if(WTERMSIG(status))
{
printf("Process %d terninated with term signal\n",pipeList[pipeList.size()-1].pid)
}
else if(WCOREDUMP(status))
{
printf("Process %d terninated with core dump\n",pipeList[pipeList.size()-1].pid)
}
}
//Передача значений из дочерних процессов
//в родительский
if(pid == 0)
{
//Закрыть трубу в дочернем процессе на чтение
if(close(pipeList[pipeList.size()-1].fadr[0]) == 0)
{
//Запись значений, т.е.
//передача в родительский процесс
if(write(pipeList[pipeList.size()-1].fadr[1],&mainRes,sizeof(result)) > 0)
//Закрыть трубу в дочернем процессе на запись
if(close(pipeList[pipeList.size()-1].fadr[1])<0) printf("\n 174 Ошибка - %s\n", strerror(errno));
}
else printf("\n 176Ошибка - %s\n", strerror(errno));
}
else if(pid > 0)
{
//Проматриваем все дочерние процессы,
//которые мы создали в текущем родительском процессе
while(pipeList[pipeList.size()-1].pid == 0)
{
struct result bufres;
//Производим чтение переданных
//значений из дочернего
if(read(pipeList[pipeList.size()-1].fadr[0],&bufres,sizeof(result)) >= 0)
{
//Закрыть трубу на чтение
if(close(pipeList[pipeList.size()-1].fadr[0])<0) printf("\n 193 Ошибка - %s\n", strerror(errno));
//Сравнение сзначений
if(bufres.count > mainRes.count) mainRes = bufres;
//Закрыть трубу на запись
if(close(pipeList[pipeList.size()-1].fadr[1])<0) printf("\n 197 Ошибка - %s\n", strerror(errno));
//Удаление последнего
//(т.к. это труба для взаимодействия
// с дочерним процессом) элемента списка
printf("\npipeList.pid = %d\n, Путь - %s",pipeList[pipeList.size()-1].pid,path);
if(pipeList[pipeList.size()-1].pid == 0) pipeList.pop_back();
}
else
{
printf("\n 206 Ошибка - %s PID - %d", strerror(errno),getpid());
}
//printf("\npipelist.size = %zu\n",pipeList.size());
//printf("\npipelist.pid = %d\n",pipeList[pipeList.size()-1].pid);
}
//printf("\nPid - %d\n",pipeList[pipeList.size()-1].pid);
//Проверка на конец списка
//т.е. остались ли трубы
//printf("\npipeList.size = %zu\n",pipeList.size());
if(pipeList.size() != 0)
{
//Проверка на то, что мы находимся
//в дочернем процессе, а не в корневом
//printf("\nПроцесс - %d PID - %d\n",pipeList[pipeList.size()-1].pid,getpid());
if(pipeList.size()>1)
{
//Передаем из дочернего процесса
//(который сейчас является родительским)
//значения
//Закрыть трубу на чтение
if(close(pipeList[pipeList.size()-1].fadr[0]) == 0)
{
//Запись значений
if (write(pipeList[pipeList.size()-1].fadr[1],&mainRes,sizeof(result)) > 0)
{
if(close(pipeList[pipeList.size()-1].fadr[1])<0) printf("\n 234 Ошибка - %s", strerror(errno));
}
else printf("\n 236 Ошибка - %s", strerror(errno));
}
else printf("\n 238 Ошибка - %s", strerror(errno));
}
else
{
//Корневой процесс
struct result bufres;
//Чтение значений из дочерних процессов
//printf("\nPIPELISTSIZE - %zu\n",pipeList.size());
if(read(pipeList[pipeList.size()-1].fadr[0],&bufres,sizeof(result)) >= 0)
{
//printf("\nPIPELISTSIZE - %zu\n",pipeList.size());
//Закрыть трубу на чтение
if(close(pipeList[pipeList.size()-1].fadr[0])<0) printf("\n 253 Ошибка - %s\n", strerror(errno));
//Сравнение значений из дочених процессов с
//корневым-родительским
if(bufres.count > mainRes.count) mainRes = bufres;
//Закрыть трубу на запись
if(close(pipeList[pipeList.size()-1].fadr[1])<0) printf("\n 258 Ошибка - %s\n", strerror(errno));
//Удаление последней трубы (последнего элемента списка)
if(pipeList[pipeList.size()-1].pid == 0) pipeList.pop_back();
}
else printf("\n Ошибка - %s\n", strerror(errno));
printf("\nРезультат:\nКаталог - %s Количество файлов со знаком ~ - %d\n", mainRes.dir, mainRes.count);
}
}
}
if(errno != 0) printf("\n Ошибка - %s\n", strerror(errno));
}
else printf("\n Ошибка - %s", strerror(errno));
return 0;
}
int main()
{
GetDir();
printf("\n");
return 0;
}
Ответы (1 шт):
Автор решения: joker
→ Ссылка
stat принимает только полный путь, а вы даёте начиная с точки .\filename. Пишите начиная не с точки а с getcwd(...).