как пользоваться std::filesystem::directory_iterator?
От: B0FEE664  
Дата: 05.09.23 13:37
Оценка: 3 (1)
На данный момент я пользуюсь std::experimental::filesystem::directory_iterator из gcc под Debian.
В <experimental/filesystem> есть такой define:
#define __cpp_lib_experimental_filesystem 201406
(если это важно)

При использовании fs::directory_iterator::increment на каталоге, в котором вторая нить (ну или другой процесс) создаёт или удаляет файл, возникает ошибка при инкременте итератора.
Т.е. ++it может бросить исключение.
Соответственно есть желание использовать:
directory_iterator&amp; increment( std::error_code&amp; ec );,
но после некоторого размышления возникли обоснованные сомнения в возможности использовать directory_iterator для таких случаев.

Если один процесс всё время создаёт и удаляет некие файлы в каталоге, а другой пытается просмотреть весь список файлов, то как это сделать?
Допустим вызов it.increment(errCode) вернул ошибку. Что следует предпринять в этом случае? Попытаться вызвать it.increment(errCode) ещё раз? Начать сначала?
И вообще, что должно происходить в таком случае?
Это ошибка в реализации std::experimental::filesystem под Debian для файловой системы ext4?
Если — да, то исправлена ли это ошибка в новых версиях?
Или это не ошибка и так и задумано? Тогда как этим пользоваться?
И каждый день — без права на ошибку...
Отредактировано 05.09.2023 14:41 B0FEE664 . Предыдущая версия .
Re: как пользоваться std::filesystem::directory_iterator?
От: reversecode google
Дата: 05.09.23 13:50
Оценка:
iterator внутри использует инкремент
и если ошибка, бросает ексепшн
так что крутите итератор на месте пока ошибка

здесь фокус а есть ли тред сейф самих апи в при котором одно апи системы удаляет а другое при этом ищет
хз не вникал
Re: как пользоваться std::filesystem::directory_iterator?
От: DiPaolo Россия  
Дата: 05.09.23 14:03
Оценка:
BFE>Допустим вызов it.increment(errCode) вернул ошибку. Что следует предпринять в этом случае? Попытаться вызвать it.increment(errCode) ещё раз? Начать сначала?
Зависит от логики приложения. Первое, что приходит на ум, и самое простое — начинать итерирование заново. Но если у вас ваш второй процесс очень часто удаляет/добавляет файлы, то нужно как-то иначе организовать обработку.

BFE>И вообще, что должно происходить в таком случае?

BFE>Это ошибка в реализации std::experimental::filesystem под Debian для файловой системы ext4?
BFE>Если — да, то исправлена ли это ошибка в новых версиях?
BFE>Или это не ошибка и так и задумано? Тогда как этим пользоваться?

https://en.cppreference.com/w/cpp/filesystem/directory_iterator:

If a file or a directory is deleted or added to the directory tree after the directory iterator has been created, it is unspecified whether the change would be observed through the iterator.

Патриот здравого смысла
Отредактировано 05.09.2023 15:19 DiPaolo . Предыдущая версия .
Re[2]: как пользоваться std::filesystem::directory_iterator?
От: B0FEE664  
Дата: 05.09.23 14:33
Оценка:
Здравствуйте, DiPaolo, Вы писали:

DP>Зависит от логики приложения. Первое, что приходит на ум, и самое простое — начинать итерирование заново. Но если у вас ваш второй процесс очень часто удаляет/добавляет файлы, то нужно как-то иначе организовать обработку.

Если мне просто нужно получить список файлов и не страшно, что он через секунду устареет, тогда как быть?

DP>https://en.cppreference.com/w/cpp/filesystem/directory_iterator:

DP>

DP>If a file or a directory is deleted or added to the directory tree after the directory iterator has been created, it is unspecified whether the change would be observed through the iterator.

— это понятно — нет способа гарантировать что проход будет только по существующим файлам, но это не значит, что при проходе по списку итератором должна возникать ошибка.
Допустим у нас есть итератор на файл и этот файл кто-то удаляетудалил, значит it->exists() вернёт false, а ++it передвинет итератор на следующий файл. Или же ++it бросит исключение?
И каждый день — без права на ошибку...
Отредактировано 05.09.2023 14:35 B0FEE664 . Предыдущая версия .
Re[2]: как пользоваться std::filesystem::directory_iterator?
От: B0FEE664  
Дата: 05.09.23 14:39
Оценка:
Здравствуйте, reversecode, Вы писали:

R>iterator внутри использует инкремент

R>и если ошибка, бросает ексепшн
R>так что крутите итератор на месте пока ошибка
Судя по этому:

If the directory_iterator reports an error or is advanced past the last directory entry, it becomes equal to the default-constructed iterator, also known as the end iterator. Two end iterators are always equal, dereferencing or incrementing the end iterator is undefined behavior.

так делать. таки, нельзя.

R>здесь фокус а есть ли тред сейф самих апи в при котором одно апи системы удаляет а другое при этом ищет

Иначе и быть не может (во всех современных системах).
И каждый день — без права на ошибку...
Re[3]: как пользоваться std::filesystem::directory_iterator?
От: reversecode google
Дата: 05.09.23 15:01
Оценка:
можно
только не на месте
а дальше итерироваться

да кстати что за ошибку выбрасывает?
Re[3]: как пользоваться std::filesystem::directory_iterator?
От: DiPaolo Россия  
Дата: 05.09.23 15:22
Оценка:
DP>>Зависит от логики приложения. Первое, что приходит на ум, и самое простое — начинать итерирование заново. Но если у вас ваш второй процесс очень часто удаляет/добавляет файлы, то нужно как-то иначе организовать обработку.
BFE>Если мне просто нужно получить список файлов и не страшно, что он через секунду устареет, тогда как быть?
Ну проверять надо. Я точно не могу сказать. Можно бряку поставить, упасть в нее, удалить/добавить файл и протестить поведение.

BFE>- это понятно — нет способа гарантировать что проход будет только по существующим файлам, но это не значит, что при проходе по списку итератором должна возникать ошибка.

BFE>Допустим у нас есть итератор на файл и этот файл кто-то удаляетудалил, значит it->exists() вернёт false, а ++it передвинет итератор на следующий файл. Или же ++it бросит исключение?

См. выше. Скорее всего будет зависеть от ОСи и компилятора.
Патриот здравого смысла
Re[4]: как пользоваться std::filesystem::directory_iterator?
От: reversecode google
Дата: 05.09.23 15:26
Оценка:
частично беру свои слова обратно
все таки есть долбоебы в коммтете с++
в юниксе если ошибка то итератор сброситься и при проверке вернет пустоту
так что итераця провалиться так и этак

в виндовой имплементации можно дальше итерироваться
Re[3]: как пользоваться std::filesystem::directory_iterator?
От: SaZ  
Дата: 05.09.23 22:57
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Здравствуйте, DiPaolo, Вы писали:


DP>>Зависит от логики приложения. Первое, что приходит на ум, и самое простое — начинать итерирование заново. Но если у вас ваш второй процесс очень часто удаляет/добавляет файлы, то нужно как-то иначе организовать обработку.

BFE>Если мне просто нужно получить список файлов и не страшно, что он через секунду устареет, тогда как быть?

А не хотите через вызов какого-нибудь ls и парсинг выхлопа? Так себе решение, но при столь неточной постановке задачи мне кажется что оно имеет право на жизнь.

Если есть возможность минимально менять второй процесс, то ситуация разруливается через лок файлы. Либо можно извращаться с инжектом и приостановкой чужих процессов на время индексации, но это тоже так себе идея. Проще уточнить задачу.
Re[4]: как пользоваться std::filesystem::directory_iterator?
От: B0FEE664  
Дата: 18.09.23 16:00
Оценка:
Здравствуйте, SaZ, Вы писали:

SaZ>А не хотите через вызов какого-нибудь ls и парсинг выхлопа?

Нет, конечно.

SaZ>Так себе решение, но при столь неточной постановке задачи мне кажется что оно имеет право на жизнь.

Я не пытаюсь решить задачу. Я пытаюсь понять, как пользоваться std::filesystem::directory_iterator. Допустим, мне захотелось написать ls. Как?

SaZ>Если есть возможность минимально менять второй процесс, то ситуация разруливается через лок файлы. Либо можно извращаться с инжектом и приостановкой чужих процессов на время индексации, но это тоже так себе идея. Проще уточнить задачу.

Неужели ls делает это через лок файлы? Не верю.
И каждый день — без права на ошибку...
Re: как пользоваться std::filesystem::directory_iterator?
От: B0FEE664  
Дата: 13.12.23 16:14
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Если один процесс всё время создаёт и удаляет некие файлы в каталоге, а другой пытается просмотреть весь список файлов, то как это сделать?


Сегодня ещё раз вернулся к этой теме и нашёл следующее:
http://www.eel.is/c++draft/fs.race.behavior#1

A file system race is the condition that occurs when multiple threads, processes, or computers interleave access and modification of the same object within a file system.
Behavior is undefined if calls to functions provided by subclause [filesystems] introduce a file system race.


Правильно ли я понимаю, что вот этот пример из стандарта:
using namespace std::filesystem;
// use possibly cached last write time to minimize disk accesses
for (auto&& x : directory_iterator("."))
{
  std::cout << x.path() << " " << x.last_write_time() << std::endl;
}


являет собой пример неопределённого поведения в том случае, если какая-либо программа в момент выполнения этого цикла создаст или удалит файл из текущего (".") каталога?
И каждый день — без права на ошибку...
Re[2]: как пользоваться std::filesystem::directory_iterator?
От: reversecode google
Дата: 13.12.23 16:21
Оценка:
вроде же тогда еще закрыли вопрос ?
я смотрел в гцц и в msvc имплементации этого
они по разному работают
в винде все дефинед
под линуксой андефинед
Re[3]: как пользоваться std::filesystem::directory_iterator?
От: B0FEE664  
Дата: 13.12.23 17:19
Оценка:
Здравствуйте, reversecode, Вы писали:

R>вроде же тогда еще закрыли вопрос ?

R>я смотрел в гцц и в msvc имплементации этого
R>они по разному работают
R>в винде все дефинед
R>под линуксой андефинед

Ага. Закрыли не решив.
Но дело даже не в этом, а в том, что по стандарту получается, что это вообще undefined behavior.

А ещё в стандарте прописан метод std::filesystem::directory_entry::refresh. Однако может он помочь или нет — мне не ясно...
И каждый день — без права на ошибку...
Re[4]: как пользоваться std::filesystem::directory_iterator?
От: reversecode google
Дата: 13.12.23 17:27
Оценка:
если в одной иплементации дефайнед в другой не дефайнед
значит итоговая не дефайнед

рефрешь не сморел не знаю

держите под рукой три stl имплементации gcc clang msvc
сразу будет проще понимать

стандарт очень тяжело бывает читать
еще тяжелее понять
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.