Search code examples
javaniofilelock

Exclusive lock on file is downgraded, when another FileChannnel for the locked file is closed


I acquire exclusive FileLock for the file, but when I create another RandomAccessFile/FileChannel for the file and close it then the FileLock is downgraded and I can acquire FileLock for the file from another process.

Following reproducible test that better describe the situation

final String path = "/tmp/test.lck";
int sleep = 20_000;

final File dbFile = new File(path);
RandomAccessFile raf = new RandomAccessFile(dbFile, "rw");
final FileLock envLock = raf.getChannel().tryLock(0, 1, false);
System.out.println("Lock acquired " + envLock);

//WE ACQUIRE THE LOCK
//CHECK WITH LSOF you will see
//lsof test.lck
//COMMAND  PID      USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
//java    5088     fefe    4uw  REG  253,2        0 8128854 test.lck

//FILE IS PROPERLY LOCKED, YOU CANNOT OBTAIN LOCK FROM ANOTHER PROCESS !!!! 
//you can run this same program from another terminal and you will not be able to get the lock , tryLock method will return null

System.out.println("going to sleep  " + sleep);
Thread.sleep(sleep);
System.out.println("after sleep  " + sleep);

final File dbFile2 = new File(path);
RandomAccessFile raf2 = new RandomAccessFile(dbFile2, "rw");
raf2.close();    
System.out.println("channel released and closed");

//AFTER THE CHANNEL IS CLOSED, YOU CAN OBTAIN LOCK FROM ANOTHER PROCESSS !!!! <--- HERE IS THE PROBLEM
//you can run this same program from another terminal and you will be able to get lock

//WE CLOSE THE CHANNEL
//CHECK WITH LSOF you will see
//YOU CHAN SEE THE FD CHANGE FROM uw to u
//    COMMAND  PID      USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
//    java    5088      fefe    4u  REG  253,2        0 8128854 test.lck


System.out.println("going to sleep  " + sleep);
Thread.sleep(5 * sleep);
System.out.println("after sleep  " + sleep);

The problem is that after I create the RandomAccessFile for the same file path for which I owned the FileLock and when I close the RandomAccessFile I can acquire the lock on the File from another process. I think this is strange behaviour, and is either bug or I am missing something obvious. How can I correctly lock the file, that the lock will not be released after subsequent creation of RandomAccessFile for the same file(for example when I want to check if I hold the lock etc...). I have tested it with the JDK8 and JDK11 and same behaviour. My file system is xfs


Solution

  • I could not reproduce on Windows.

    From the Javadoc of FileLock:

    File locks are held on behalf of the entire Java virtual machine.

    This file-locking API is intended to map directly to the native locking facility of the underlying operating system. Thus the locks held on a file should be visible to all programs that have access to the file, regardless of the language in which those programs are written.

    On some systems, closing a channel releases all locks held by the Java virtual machine on the underlying file regardless of whether the locks were acquired via that channel or via another channel open on the same file. It is strongly recommended that, within a program, a unique channel be used to acquire all locks on any given file.