You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ka...@apache.org on 2013/04/10 10:04:52 UTC

svn commit: r1466362 - /db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java

Author: kahatlen
Date: Wed Apr 10 08:04:52 2013
New Revision: 1466362

URL: http://svn.apache.org/r1466362
Log:
DERBY-6092: IOException when closing LOBFile at end of transaction

A bug in Java 5 may cause IOException if two threads attempt to
close the same RandomAccessFile at the same time.

Avoid this situation by removing the LOBFile from the list of open
files before closing it from LOBStreamControl's finalizer. Then the
cleanup code at the end of the transaction won't find the file and
try to close it if the finalizer is about to close it.

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java?rev=1466362&r1=1466361&r2=1466362&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java Wed Apr 10 08:04:52 2013
@@ -531,8 +531,22 @@ class LOBStreamControl {
      * @throws IOException if the file cannot be closed or deleted
      */
     private void releaseTempFile(LOBFile file) throws IOException {
-        file.close();
+        // Remove the file from the list of open files *first*, then close it.
+        //
+        // Why? This code may be called from finalize(), and may end up running
+        // at the same time the transaction is committed or rolled back. If two
+        // threads call RandomAccessFile.close() at the same time, Java 5 could
+        // fail (see DERBY-6092). By removing it from the list before closing
+        // it, we make sure that EmbedConnection.clearLOBMapping() won't see
+        // it if we get to the file first. Conversely, if clearLOBMapping()
+        // gets to it first, the call to removeLobFile() will block until
+        // clearLOBMapping() is done, so we won't attempt to close the file
+        // until after clearLOBMapping() is done, rather than at the same time.
+        //
+        // Calling close() concurrently is safe on Java 6 and newer, after the
+        // fix for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6322678 .
         conn.removeLobFile(file);
+        file.close();
         deleteFile(file.getStorageFile());
     }