From 8adcb7649edd6db23921d37647fe2deb58f8d666 Mon Sep 17 00:00:00 2001 From: chegar Date: Wed, 13 Nov 2013 16:44:12 +0000 Subject: [PATCH] 8022213: Intermittent test failures in java/net/URLClassLoader Reviewed-by: dxu, alanb --- .../URLClassLoader/closetest/CloseTest.java | 3 +- .../net/URLClassLoader/closetest/Common.java | 37 +--- .../closetest/GetResourceAsStream.java | 2 + .../jdk/testlibrary/FileUtils.java | 169 ++++++++++++++++++ 4 files changed, 180 insertions(+), 31 deletions(-) create mode 100644 test/lib/testlibrary/jdk/testlibrary/FileUtils.java diff --git a/test/java/net/URLClassLoader/closetest/CloseTest.java b/test/java/net/URLClassLoader/closetest/CloseTest.java index 598b1e6b5..a1416271f 100644 --- a/test/java/net/URLClassLoader/closetest/CloseTest.java +++ b/test/java/net/URLClassLoader/closetest/CloseTest.java @@ -25,7 +25,8 @@ * @test * @bug 4167874 * @library ../../../../com/sun/net/httpserver - * @build FileServerHandler + * @library /lib/testlibrary + * @build FileServerHandler jdk.testlibrary.FileUtils * @run shell build.sh * @run main/othervm CloseTest * @summary URL-downloaded jar files can consume all available file descriptors diff --git a/test/java/net/URLClassLoader/closetest/Common.java b/test/java/net/URLClassLoader/closetest/Common.java index 69332acaf..fc06fb3a9 100644 --- a/test/java/net/URLClassLoader/closetest/Common.java +++ b/test/java/net/URLClassLoader/closetest/Common.java @@ -23,6 +23,9 @@ import java.io.*; import java.net.*; +import java.nio.file.Files; +import jdk.testlibrary.FileUtils; +import static java.nio.file.StandardCopyOption.*; public class Common { @@ -39,42 +42,16 @@ public class Common { if (!src.isFile()) { throw new RuntimeException ("File not found: " + src.toString()); } - dst.delete(); - dst.createNewFile(); - FileInputStream i = new FileInputStream (src); - FileOutputStream o = new FileOutputStream (dst); - byte[] buf = new byte [1024]; - int count; - while ((count=i.read(buf)) >= 0) { - o.write (buf, 0, count); - } - i.close(); - o.close(); + Files.copy(src.toPath(), dst.toPath(), REPLACE_EXISTING); } catch (IOException e) { throw new RuntimeException (e); } } - static void rm_minus_rf (File path) { - if (!path.exists()) { + static void rm_minus_rf (File path) throws IOException, InterruptedException { + if (!path.exists()) return; - } - if (path.isFile()) { - if (!path.delete()) { - throw new RuntimeException ("Could not delete " + path); - } - } else if (path.isDirectory ()) { - String[] names = path.list(); - File[] files = path.listFiles(); - for (int i=0; i MAX_RETRY_DELETE_TIMES) + throw new IOException("File still exists after " + times + " waits."); + Thread.sleep(RETRY_DELETE_MILLIS); + } + break; + } catch (NoSuchFileException | DirectoryNotEmptyException x) { + throw x; + } catch (IOException x) { + // Backoff/retry in case another process is accessing the file + times++; + if (ioe == null) + ioe = x; + else + ioe.addSuppressed(x); + + if (times > MAX_RETRY_DELETE_TIMES) + throw ioe; + Thread.sleep(RETRY_DELETE_MILLIS); + } + } + } + + /** + * Deletes a directory and its subdirectories, retrying if necessary. + * + * @param dir the directory to delete + * + * @throws IOException + * If an I/O error occurs. Any such exceptions are caught + * internally. If only one is caught, then it is re-thrown. + * If more than one exception is caught, then the second and + * following exceptions are added as suppressed exceptions of the + * first one caught, which is then re-thrown. + */ + public static void deleteFileTreeWithRetry(Path dir) + throws IOException + { + IOException ioe = null; + final List excs = deleteFileTreeUnchecked(dir); + if (!excs.isEmpty()) { + ioe = excs.remove(0); + for (IOException x : excs) + ioe.addSuppressed(x); + } + if (ioe != null) + throw ioe; + } + + public static List deleteFileTreeUnchecked(Path dir) { + final List excs = new ArrayList<>(); + try { + java.nio.file.Files.walkFileTree(dir, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + try { + deleteFileWithRetry0(file); + } catch (IOException x) { + excs.add(x); + } catch (InterruptedException x) { + excs.add(new IOException("Interrupted while deleting.", x)); + return FileVisitResult.TERMINATE; + } + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) { + try { + deleteFileWithRetry0(dir); + } catch (IOException x) { + excs.add(x); + } catch (InterruptedException x) { + excs.add(new IOException("Interrupted while deleting.", x)); + return FileVisitResult.TERMINATE; + } + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) { + excs.add(exc); + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException x) { + excs.add(x); + } + return excs; + } +} + -- GitLab