JDK-6522814 : a race bug in src/share/classes/java/io/File.java
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.io
  • Affected Version: 5.0u11
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2007-02-08
  • Updated: 2010-04-02
  • Resolved: 2007-02-08
Related Reports
Duplicate :  
Description
When executing the following code concurrently from many threads with a directory structure that does
not exist yet, we get "java.io.FileNotFoundException: /home/dump/129393/data/compressed/11/cost.gz
(No such file or directory)"

 File directory = new File(_directory + File.separator + Thread.currentThread().getName());
 directory.mkdirs();
 OutputStream out = new FileOutputStream(new File(directory, "cost.gz"));

This was found to be a race in Sun's J2SE code by inspection. Below, if the parent directory is created
underneath mkdirs then it never goes and makes the subdirectory:

  1144     public boolean mkdirs() {
  1145         if (exists()) {
  1146             return false;
  1147         }
  1148         if (mkdir()) {
  1149             return true;
  1150         }
  1151         File canonFile = null;
  1152         try {
  1153             canonFile = getCanonicalFile();
  1154         } catch (IOException e) {
  1155             return false;
  1156         }
  1157         String parent = canonFile.getParent();
  1158         return (parent != null) &&
  1159                (new File(parent, fs.prefixLength(parent)).mkdirs() &&
  1160                                     canonFile.mkdir());
  1161     }

The fix we've made is these two diffs:

==== J2SE 4: src/share/classes/java/io/File.java#2 (text) ====
@@ -1128,9 +1128,12 @@
        } catch (IOException e) {
            return false;
        }
-    String parent = canonFile.getParent();
-        return (parent != null) && (new File(parent).mkdirs() &&
-                                    canonFile.mkdir());
+        File parent = canonFile.getParentFile();
+        if (parent == null) {
+          return false;
+        }
+        parent.mkdirs(); // try to make the parent directory, but ignore if somebody else beats us to the punch
+        return canonFile.mkdir();
    }
    /**
==== J2SE 5: src/share/classes/java/io/File.java#3 (text) ====
@@ -1154,10 +1154,12 @@
        } catch (IOException e) {
            return false;
        }
-    String parent = canonFile.getParent();
-        return (parent != null) &&
-               (new File(parent, fs.prefixLength(parent)).mkdirs() &&
-                                    canonFile.mkdir());
+    File parent = canonFile.getParentFile();
+        if (parent == null) {
+          return false;
+        }
+        parent.mkdirs(); // try to make the parent directory, but ignore if somebody else beats us to the punch
+        return canonFile.mkdir();
    }
    /**

Comments
EVALUATION Yes, mkdirs cannot handle this case. The issue is also tracked as 4742723 where another candidate fix is attached.
08-02-2007