Почему Files.deleteDirectoryContents() устарел в Guava?

В Guava 10+ Google устарел Files.deleteDirectoryContents(). JavaDoc говорит

Устарело. Этот метод страдает от плохого обнаружения символических ссылок и условий гонки. Эта функциональность может быть поддержана должным образом только с помощью команд операционной системы, таких как rm -rf или del /s. Этот метод планируется удалить из Guava в выпуске Guava 11.0.

Я смущен тем, почему существует состояние гонки. Я думаю, что этот метод на самом деле полезен, и считаю, что обстрел операционной системы плохим решением. Могут ли авторы поделиться, почему они приняли такое решение?


person Amir Raminfar    schedule 30.11.2011    source источник
comment
Чтобы быть более ясным, я думаю, что проблема состояния гонки не является серьезной ошибкой. Многие библиотеки, такие как ArrayList, не являются потокобезопасными или имеют условия гонки. Даже у File.remove такая же проблема. Но все они задокументированы. Поэтому я надеялся услышать ответ помимо того, что уже сказано в документации о том, почему они решили сделать его устаревшим.   -  person Amir Raminfar    schedule 30.11.2011
comment
Разница между этим состоянием гонки и типичными не потокобезопасными классами заключается в том, что для него нет исправления. Напротив, вы можете решить проблемы безопасности потоков Java с классами, не поддерживающими потоки, путем синхронизации объекта блокировки. Метод, который просто не может делать то, что от него ожидают, является плохим методом.   -  person Stephen C    schedule 02.12.2011
comment
(Под отсутствием исправления я имею в виду, что никакое исправление невозможно на уровне платформы Guava или Java. Теоретически возможно исправить это на уровне операционной системы, например, если файловая система была сделана транзакционной ACID. Но не делайте этого. затаи дыхание жду...)   -  person Stephen C    schedule 02.12.2011


Ответы (4)


Я смущен тем, почему существует состояние гонки.

Например, предположим, что один поток вызывает Files.deleteDirectoryContents(), а второй поток (или внешний процесс) одновременно создает новый файл в каталоге.

Когда вы возвращаетесь со звонка, можете ли вы полагаться на то, что каталог пуст? Неа!

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

Могут ли авторы поделиться, почему они приняли такое решение?

Я думаю, что они уже есть; см. уведомление об устаревании. Если вы хотите узнать больше, попробуйте выполнить поиск в системе отслеживания проблем и в группе обсуждения Guava. Вы даже можете попытаться вежливо попросить об этом в дискуссионной группе, хотя, если ваша повестка дня состоит в том, чтобы изменить их мнение, я сомневаюсь, что вы добьетесь успеха.

person Stephen C    schedule 30.11.2011
comment
То же самое верно и для раскошеливания на ОС, не так ли? - person anders; 30.11.2011
comment
+1 Разве это не то же самое, что раскошелиться на ОС. Я думаю, что если библиотека не является потокобезопасной, она должна быть задокументирована, и разработчик должен убедиться, что они используют ее правильно. - person Amir Raminfar; 30.11.2011
comment
@ Стивен С, я не пытаюсь изменить чье-либо мнение. Я уверен, что есть веская причина, по которой это устарело. Я просто подумал, что, возможно, есть проблема, помимо условий гонки, которая заставила это сделать. Но есть много библиотек, которые имеют условия гонки. Я подумал, что, может быть, есть более веская причина. - person Amir Raminfar; 30.11.2011
comment
Гуава необычайно стремится максимально усложнить случайную ошибку... например, условия гонки. - person Louis Wasserman; 01.12.2011
comment
@AmirRaminfar - авторы также называют плохое обнаружение символических ссылок причиной устаревания. Я думаю, они имеют в виду тот факт, что трудно надежно/переносимо/дешево отличить файл от символической ссылки на файл в чистой Java. И вы должны для этого метода. FWIW - это очень веские причины. Нет необходимости в лучшем ИМО. - person Stephen C; 01.12.2011
comment
@StephenC, это кажется хорошим ответом. Я бы принял это, если бы вы ответили. :0 - person Amir Raminfar; 01.12.2011
comment
@AmirRaminfar - я бы так и сделал, за исключением того, что вы не подняли это в своем вопросе (в отличие от ... вы действительно подняли условие гонки), и, следовательно, я предположил, что вы поняли, что они имели в виду об обнаружении символических ссылок . - person Stephen C; 02.12.2011
comment
@anders - да, будет. Но, по крайней мере, это больше не проблема Гуавы :-) - person Stephen C; 02.12.2011

Состояние гонки потенциально хуже, чем «каталог может быть не пустым», и это частично из-за плохого обнаружения символических ссылок. Рассмотрим этот фрагмент кода:

// Symbolic links will have different canonical and absolute paths
if (!directory.getCanonicalPath().equals(directory.getAbsolutePath())) {
  return;
}
... delete its contents ...

Если directory является обычным каталогом во время проверки, но символической ссылкой на / после, deleteDirectoryContents с радостью попытается стереть всю файловую систему.

Возможно, есть обходной путь, но мы его не нашли. И делать специальные исправления для потенциальной ошибки безопасности страшно.

person Chris Povirk    schedule 02.12.2011

Дополнительные примеры обнаружения неработающих символических ссылок см. в разделе эти ошибки, отправленные пользователями.

Короче говоря, невозможно стереть каталог, если вы не укажете канонический путь к этому каталогу. Если /tmp является ссылкой на /some/other/directory, deleteDirectoryContents не может стереть /tmp/mytempdirectory. Возможно, здесь тоже есть возможный обходной путь, но мы развели руками.

person Chris Povirk    schedule 02.12.2011

Ты серьезно? Вы пытаетесь решить многопоточные операции:

Например, предположим, что один поток вызывает Files.deleteDirectoryContents(), а второй поток (или внешний процесс) одновременно создает новый файл в каталоге. Когда вы возвращаетесь со звонка, можете ли вы полагаться на то, что каталог пуст? Неа!

А как насчет того, чтобы над каталогом работал другой процесс??? Это невозможно решить, и вы не должны обрабатывать транзакции, поскольку это просто невозможно. И аргумент, что кто-то делает символическую ссылку на корень, поэтому я удаляю всю файловую систему - не должны ли права доступа к файловой системе обрабатывать это? И если вы выполняете такую ​​операцию как root, вы должны знать, что делаете. Насчет запрета удаления файлов вообще в файловой системе, это опасно!!! Тогда я буду использовать другую библиотеку, если авторы Гуавы будут решать такие идиотские задачи.

person Milan Vondra    schedule 20.02.2013