Domanda

I hava un programma Java che ha bisogno di monitorare un albero di directory per i cambiamenti. Ho codice JNI che utilizza ReadDirectoryChangesW(). La directory viene aperta come:

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

e poi mi passa dirHandle a ReadDirectoryChangesW(). Tutto questo funziona bene.

Il problema è che altre parti del codice (sul lato Java) usano File.setLastModified() ai file "touch" o directory (aggiornare i loro timestamp di essere "ora"). Questo funziona in genere; tuttavia, non riesce quando ha cercato di "toccare" la directory che è stato aperto utilizzando CreateFile().

Per vedere ciò che di errore di Windows è effettivamente in corso, ho guardato la fonte JDK per File.setLastModified() e reimplementato nel mio proprio codice con l'aggiunta di stampare l'errore da GetLastError(); l'errore è:

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

WTF? E 'il stesso processo. Ho anche passato FILE_SHARE_READ e FILE_SHARE_WRITE a CreateFile().

C'è un modo per fare questo lavoro?

Ulteriori informazioni

L'implementazione del codice nativo del File.setLastModified() nel JDK fa un:

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

Se cambio il primo 0 a FILE_SHARE_READ | FILE_SHARE_WRITE, tutto funziona. Così sembra che l'attuazione JDK è un po 'rotto. : (

Quindi la mia domanda ora diventa:? C'è un modo per fare questo lavoro senza la necessità di usare la mia (ri) attuazione di File.setLastModified()

È stato utile?

Soluzione

Anche se il messaggio di errore è un po 'fuorviante, in questo caso, quello che stai vedendo è un comportamento normale.

Con l'apertura della directory con il set dwShareMode a zero, il JDK è, in effetti, chiedendo per l'accesso esclusivo, che farà sì che qualsiasi altro tentativo di accesso a fallire con un errore di violazione di condivisione. Ciò vale anche per accessi da altri processi e da dentro il proprio processo.

Il CreateFile documentazione descrive il parametro dwShareMode:

  

Se questo parametro è zero e CreateFile riesce, il file o il dispositivo non possono essere condivise e non può essere aperto di nuovo fino a quando la maniglia per il file o il dispositivo è chiuso.

     

Non è possibile richiedere una modalità di condivisione che è in conflitto con la modalità di accesso specificato in una richiesta esistente che ha un handle aperto. CreateFile fallirebbe e la funzione GetLastError sarebbe tornato ERROR_SHARING_VIOLATION.

Così, sembra che hai risposto alla tua domanda:. Hai bisogno di una funzione di setLastModified personalizzata che specifica FILE_SHARE_READ | FILE_SHARE_WRITE quando si accede alla directory

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top