JDK-6620010 : (fc) FileChannel.tryLock leaves FileLock on lockList if I/O error occurs
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 5.0,5.0u17
  • Priority: P4
  • Status: Closed
  • Resolution: Cannot Reproduce
  • OS: linux,solaris_10
  • CPU: x86,sparc
  • Submitted: 2007-10-22
  • Updated: 2011-02-16
  • Resolved: 2009-09-01
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other JDK 6 JDK 7
5.0u21-revFixed 6u16-revFixed 7Resolved
Related Reports
Duplicate :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_08"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_08-b03)
Java HotSpot(TM) Client VM (build 1.5.0_08-b03, mixed mode, sharing)


ADDITIONAL OS VERSION INFORMATION :
Linux 2.6.20-16-generic #2 SMP Sun Sep 23 19:50:39 UTC 2007 i686 GNU/Linux

But probably applies to other OSs as well

A DESCRIPTION OF THE PROBLEM :
The semantics of lock() and tryLock() are different when the underlying lock cannot be obtained due to an IOException.

lock() removes the lock from the lockList wheras tryLock() does not.  One effect of this is that if  tryLock() is called again, an OverlappingFileLockException is thrown instead of a more appropriate IOException.

The bug can be clearly observed by looking at the two methods:

    public FileLock lock(long position, long size, boolean shared)
	throws IOException
    {
...
        checkList(position, size);
        addList(fli);
...
        try {
...
        } catch (IOException e) {
            removeList(fli);
            throw e;
        }
...
  }

   public FileLock tryLock(long position, long size, boolean shared)
	throws IOException
    {
...
        checkList(position, size);
        addList(fli);
...
    }

The fix it to modify tryLock() to catch the IOException, call removeList(), and rethrow the IOException

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
    public static void main(String[] args) throws IOException {
        RandomAccessFile raf = new RandomAccessFile("/tmp/foo", "rw");
        FileChannel channel = raf.getChannel();
        
        try {
            channel.lock();
        }
        catch (Throwable t) {
            System.out.println(t);
        }
        
        try {
            channel.lock();
        }
        catch (Throwable t) {
            System.out.println(t);
        }
        
        try {
            channel.tryLock();
        }
        catch (Throwable t) {
            System.out.println(t);
        }
        
        try {
            channel.tryLock();
        }
        catch (Throwable t) {
            System.out.println(t);
        }
    }



EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
java.io.IOException: No locks available
java.io.IOException: No locks available
java.io.IOException: No locks available
java.io.IOException: No locks available

ACTUAL -
java.io.IOException: No locks available
java.io.IOException: No locks available
java.io.IOException: No locks available
java.nio.channels.OverlappingFileLockException

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;

public class FileLockBug {

    public static void main(String[] args) throws IOException {
        RandomAccessFile raf = new RandomAccessFile("/tmp/foo", "rw");
        FileChannel channel = raf.getChannel();
        
        try {
            channel.lock();
        }
        catch (Throwable t) {
            System.out.println(t);
        }
        
        try {
            channel.lock();
        }
        catch (Throwable t) {
            System.out.println(t);
        }
        
        try {
            channel.tryLock();
        }
        catch (Throwable t) {
            System.out.println(t);
        }
        
        try {
            channel.tryLock();
        }
        catch (Throwable t) {
            System.out.println(t);
        }
    }
    
}

---------- END SOURCE ----------

Comments
EVALUATION The new file system API (added via 4313887) included significant updates to the FileChannel implementation with the result that this bug no longer exists.
16-02-2009

EVALUATION The submitter is correct. Will fix in jdk7 and 6open.
23-10-2007