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

XMLWordPrintable

    • Type: Bug
    • Resolution: Fixed
    • Priority: P4
    • 22
    • Affects Version/s: 7u80, 8u45, 9
    • Component/s: core-libs
    • b11
    • x86
    • linux_ubuntu, os_x
    • Verified

        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.

              Assignee:
              Brian Burkhalter
              Reporter:
              Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              7 Start watching this issue

                Created:
                Updated:
                Resolved: