Pregunta

Me HAVA un programa Java que necesita supervisar un árbol de directorios para los cambios. Tengo código JNI que utiliza ReadDirectoryChangesW(). El directorio se abre como:

HANDLE dirHandle = CreateFile(
    path, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL
);

y luego me pase a dirHandle ReadDirectoryChangesW(). Todo esto funciona bien.

El problema es que otras partes del código (en el lado de Java) utilizan File.setLastModified() a los archivos "toque" o directorios (actualicen sus marcas de tiempo para ser "ahora"). Esto funciona en general; sin embargo, se produce un error cuando se trató de "tocar" al directorio que se abre mediante CreateFile().

Para ver qué error de Windows que está ocurriendo en realidad, miré a la fuente de JDK para File.setLastModified() y reimplantado en mi propio código con la adición de imprimir el error de GetLastError(); el error es:

ERROR_SHARING_VIOLATION (error 32)
"The process cannot access the file because it is being used by another process."

WTF? Es el mismo proceso. Incluso pasé FILE_SHARE_READ y FILE_SHARE_WRITE a CreateFile().

¿Hay una manera de hacer este trabajo?

Más información

La implementación de código nativo de File.setLastModified() en el JDK hace un:

h = CreateFileW(pathbuf, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);

Si cambio de la primera a 0 FILE_SHARE_READ | FILE_SHARE_WRITE, funciona todo. Así que parece que la implementación JDK es un poco roto. : (

Así que mi pregunta ahora es: ¿Hay una manera de hacer este trabajo sin tener que usar mi propia (re) puesta en práctica de File.setLastModified()

¿Fue útil?

Solución

A pesar de que el mensaje de error es un poco engañoso en este caso, lo que se está viendo es un comportamiento normal.

Al abrir el directorio con el conjunto dwShareMode a cero, el JDK es, en efecto, pidiendo acceso exclusivo, lo que hará que cualquier otro intento de acceso a fallar con un error compartido de violación. Esto se aplica igualmente a los accesos y de otros procesos dentro de su propio proceso.

El CreateFile documentación describe el parámetro dwShareMode:

  

Si este parámetro es cero y CreateFile tiene éxito, el archivo o dispositivo no se pueden compartir y no se puede abrir hasta que la manilla en el fichero o dispositivo está cerrado.

     

No se puede solicitar un modo de uso compartido que entra en conflicto con el modo de acceso que se especifica en una solicitud existente que tiene un identificador abierto. CreateFile fallaría y la función GetLastError volvería ERROR_SHARING_VIOLATION.

Por lo tanto, parece que haya respondido a su propia pregunta:. Necesite una función personalizada que especifica setLastModified FILE_SHARE_READ | FILE_SHARE_WRITE al acceder al directorio

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top