Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8114830

(fs) Files.copy fails due to interference from something else changing the file system

    Details

    • Type: Bug
    • Status: Open
    • Priority: P4
    • Resolution: Unresolved
    • Affects Version/s: 7u80, 8u45, 9
    • Fix Version/s: tbd
    • Component/s: core-libs
    • Labels:
    • Subcomponent:
    • Understanding:
      Fix Understood
    • CPU:
      x86
    • OS:
      os_x

      Description

      FULL PRODUCT VERSION :
      Java(TM) SE Runtime Environment (build 1.7.0_80-b15)

      Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
      Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

      Java(TM) SE Runtime Environment (build pap6470sr5-20130619_01(SR5))
      IBM J9 VM (build 2.6, JRE 1.7.0 AIX ppc64-64 Compressed References 20130617_152572 (JIT enabled, AOT enabled)
      J9VM - R26_Java726_SR5_20130617_1436_B152572
      JIT - r11.b04_20130528_38954ifx1
      GC - R26_Java726_SR5_20130617_1436_B152572_CMPRSS
      J9CL - 20130617_152572)
      JCL - 20130616_01 based on Oracle 7u25-b12


      ADDITIONAL OS VERSION INFORMATION :
      Ubuntu 12.04.5
      Mac OS X 10.9.5
      AIX oslevel 6.1.0.0

      A DESCRIPTION OF THE PROBLEM :
      Execution of Files.copy with StandardCopyOption.REPLACE_EXISTING may unexpectedly result in FileAlreadyExistsException.
      This is due to the possible interleaving of another process or another thread creating the same target file.
      I think that this case should be handled internally by the copy method; alternatively the documentation of the copy method should be amended, in jdk 8u45 the javadoc entry for the copy method states:

      throws FileAlreadyExistsException - if the target file exists but cannot be replaced because the REPLACE_EXISTING option is not specified (optional specific exception)

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the attached source code


      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      java.nio.file.FileAlreadyExistsException: target
      at sun.nio.fs.UnixException.translateToIOException(UnixException.java:88)
      at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
      at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
      at sun.nio.fs.UnixCopyFile.copyFile(UnixCopyFile.java:243)
      at sun.nio.fs.UnixCopyFile.copy(UnixCopyFile.java:581)
      at sun.nio.fs.UnixFileSystemProvider.copy(UnixFileSystemProvider.java:253)
      at java.nio.file.Files.copy(Files.java:1274)
      at CopyTest$1.run(CopyTest.java:26)
      at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
      at java.util.concurrent.FutureTask.run(FutureTask.java:266)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at java.lang.Thread.run(Thread.java:745)


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.io.IOException;
      import java.nio.file.FileAlreadyExistsException;
      import java.nio.file.Files;
      import java.nio.file.Path;
      import java.nio.file.Paths;
      import java.nio.file.StandardCopyOption;
      import java.util.concurrent.ExecutorService;
      import java.util.concurrent.Executors;
      import java.util.concurrent.TimeUnit;
      import java.util.concurrent.atomic.AtomicBoolean;

      public class CopyTest {

          static final int N_THREADS = 2;
          
          static final Path source = Paths.get("source");
          static final Path target = Paths.get("target");

          static final AtomicBoolean running = new AtomicBoolean(true);
          
          static final Runnable copyTask = new Runnable() {
      @Override
      public void run() {
      try {
      while (running.get()) {
      Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
      }
      } catch (FileAlreadyExistsException e) {
      System.out.println("Received unexpected exception:");
      e.printStackTrace(System.out);
      } catch (IOException e) {
      e.printStackTrace();
      }
      running.set(false);
      }
          };
          
          public static void main(String[] args) throws IOException, InterruptedException {
      System.out.println("-- Init source delete target ---");
      Files.copy(CopyTest.class.getResourceAsStream("CopyTest.class"), source, StandardCopyOption.REPLACE_EXISTING);
      Files.deleteIfExists(target);
      System.out.println("-- Start copying source to target ---");
      ExecutorService es = Executors.newFixedThreadPool(N_THREADS);
      for (int i=0; i<N_THREADS; i++)
      es.submit(copyTask);
      es.shutdown();
      es.awaitTermination(5, TimeUnit.SECONDS);
          }
      }

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

      CUSTOMER SUBMITTED WORKAROUND :
      Handle the FileAlreadyExistsException either ignoring it or retrying.

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                bpb Brian Burkhalter
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                • Created:
                  Updated: