2011-11-30 11 views
9

En Guava 10+, Google está en desuso Files.deleteDirectoryContents(). JavaDoc dice¿Por qué Files.deleteDirectoryContents() está en desuso en Guava?

Obsoleto. Este método adolece de malas condiciones de detección de enlace simbólico y raza . Esta funcionalidad solo se puede admitir de forma adecuada mediante bombardeando a un comando del sistema operativo como rm -rf o del/s. Este método está programado para ser eliminado de guayaba guayaba en liberar 11,0

estoy confundido sobre por qué existe una condición de carrera. Creo que tener este método es realmente útil y encontrar el bombardeo al sistema operativo como una solución pobre. ¿Pueden los autores compartir por qué tomó esta decisión?

+0

Para ser más claros, creo que tener un problema de condición de carrera no es un error importante. Muchas librerías, como 'ArrayList' no son seguras para hilos o tienen condiciones de carrera. Incluso 'File.remove' tiene el mismo problema. Pero todos están documentados. Así que esperaba escuchar una respuesta además de lo que la documentación ya dice sobre por qué eligieron hacerlo obsoleto. –

+1

La diferencia entre esta condición de carrera y las clases típicas que no son seguras para subprocesos es que no existe una "solución" para ello. Por el contrario, puede resolver problemas de seguridad de subprocesos de Java con clases que no sean seguras para subprocesos mediante la sincronización en un objeto de bloqueo. Un método que simplemente no puede hacer lo que la gente espera que haga es un mal método. –

+0

Este es un buen punto. Gracias. –

Respuesta

5

Estoy confundido sobre por qué hay una condición de carrera.

Por ejemplo, supongamos que un subproceso llama Files.deleteDirectoryContents() y una segunda rosca (o un proceso externo) al mismo tiempo crea un nuevo archivo en el directorio.

Cuando regrese de la llamada, ¿puede confiar en que el directorio está vacío? ¡No!

De todos modos, si encuentra que la funcionalidad de este método es útil ... a pesar de sus defectos ... puede tomar una copia del código, ajustarlo e incrustarlo en su aplicación. (Simplemente verifique la licencia de código fuente de Guava y asegúrese de cumplir con ella.)

¿Pueden los autores compartir por qué tomó esta decisión?

Creo que ya tienen; ver el aviso de desaprobación. Si quiere más, intente buscar el rastreador de problemas y el grupo de discusión de Guava. Incluso podría intentar pedir educadamente al grupo de discusión, aunque si su agenda es cambiar su opinión, dudo que tenga éxito.

+4

Lo mismo sería cierto para bombardear al sistema operativo, ¿no es así? – anders

+0

+1 ¿No sería cierto lo mismo con el sistema operativo? Creo que si una biblioteca no es segura para subprocesos, debe estar documentada y debe estar a cargo del desarrollador para asegurarse de que la use correctamente. –

+0

@Stephen C, no estoy tratando de cambiar la mente de ningún cuerpo. Estoy seguro de que hay una buena razón sobre por qué esto está en desuso. Solo pensé que tal vez había un problema además de las condiciones de carrera que obligaban a hacer esto. Pero hay muchas librerías que tienen condiciones de carrera. Pensé que tal vez habría una mejor razón. –

5

La condición de anticipación es potencialmente peor que "el directorio podría no estar vacío", y esto se debe en parte a la escasa detección de enlaces simbólicos. Considere este fragmento de código:

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

Si directory es un directorio normal durante la comprobación de que un enlace simbólico a / después, deleteDirectoryContents estará feliz de tratar de limpiar todo el sistema de archivos.

Quizás haya una solución, pero no la hemos encontrado. Y hacer correcciones ad hoc para un posible error de seguridad es aterrador.

1

Para obtener más ejemplos de detección de enlace simbólico interrumpido, consulte these bugs filed by users.

En resumen, es imposible borrar un directorio a menos que proporcione la ruta canónica a ese directorio. Si /tmp es un enlace a /some/other/directory, deleteDirectoryContents no puede borrar /tmp/mytempdirectory. Tal vez hay una posible solución aquí, también, pero levantamos nuestras manos.

1

¿Habla en serio? Está intentando resolver operaciones de subprocesamiento múltiple:

Por ejemplo, suponga que un hilo llama a los archivos.deleteDirectoryContents() y un segundo hilo (o un proceso externo) crea simultáneamente un nuevo archivo en el directorio. Cuando regresa de la llamada, ¿puede confiar en que el directorio está vacío? ¡No!

¿Y qué ocurre con otro proceso que opera en el directorio? No puede ser resuelto y no debe manejar las transacciones ya que simplemente no es posible. Y el argumento de que alguien hace que enlace simbólico para rootear, así que elimino todo el sistema de archivos, ¿no debería tener derechos de acceso al sistema de archivos? Y si está ejecutando una operación como root, debe saber lo que está haciendo. ¿Qué hay de desactivar la eliminación de archivos en el sistema de archivos, es peligroso! Usaré una biblioteca diferente si los autores de la guayaba resuelven esos problemas idiotas.

Cuestiones relacionadas