Skip to content
Permalink
Browse files
8259570: (macos) tools/jpackage tests fails with 'hdiutil: couldn't e…
…ject "disk2" - Resource busy'

Reviewed-by: herrick, asemenyuk
  • Loading branch information
Alexander Matveev committed Feb 3, 2021
1 parent ffbcf1b commit bec60432ecbdc5e68b80b6cf0dc33934ee2eb2d1
@@ -437,7 +437,6 @@ private Path buildDMG( Map<String, ? super Object> params,
pb = new ProcessBuilder(
hdiutil,
"detach",
"-force",
hdiUtilVerbosityFlag,
mountedRoot.toAbsolutePath().toString());
// "hdiutil detach" might not work right away due to resource busy error, so
@@ -451,12 +450,21 @@ private Path buildDMG( Map<String, ? super Object> params,
}
});
try {
// 10 times with 3 second delays.
retryExecutor.setMaxAttemptsCount(10).setAttemptTimeoutMillis(3000)
// 10 times with 6 second delays.
retryExecutor.setMaxAttemptsCount(10).setAttemptTimeoutMillis(6000)
.execute(pb);
} catch (IOException ex) {
if (!retryExecutor.isAborted()) {
throw ex;
// Now force to detach if it still attached
if (Files.exists(mountedRoot)) {
pb = new ProcessBuilder(
hdiutil,
"detach",
"-force",
hdiUtilVerbosityFlag,
mountedRoot.toAbsolutePath().toString());
IOUtils.exec(pb);
}
}
}
}
@@ -469,10 +477,29 @@ private Path buildDMG( Map<String, ? super Object> params,
hdiUtilVerbosityFlag,
"-format", "UDZO",
"-o", finalDMG.toAbsolutePath().toString());
new RetryExecutor()
try {
new RetryExecutor()
.setMaxAttemptsCount(10)
.setAttemptTimeoutMillis(3000)
.execute(pb);
} catch (Exception ex) {
// Convert might failed if something holds file. Try to convert copy.
Path protoDMG2 = imagesRoot
.resolve(APP_NAME.fetchFrom(params) + "-tmp2.dmg");
Files.copy(protoDMG, protoDMG2);
try {
pb = new ProcessBuilder(
hdiutil,
"convert",
protoDMG2.toAbsolutePath().toString(),
hdiUtilVerbosityFlag,
"-format", "UDZO",
"-o", finalDMG.toAbsolutePath().toString());
IOUtils.exec(pb);
} finally {
Files.deleteIfExists(protoDMG2);
}
}

//add license if needed
if (Files.exists(getConfig_LicenseFile(params))) {
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,31 +29,31 @@
import java.util.function.Supplier;

public final class RetryExecutor {
RetryExecutor() {
public RetryExecutor() {
setMaxAttemptsCount(5);
setAttemptTimeoutMillis(2 * 1000);
}

RetryExecutor setMaxAttemptsCount(int v) {
public RetryExecutor setMaxAttemptsCount(int v) {
attempts = v;
return this;
}

RetryExecutor setAttemptTimeoutMillis(int v) {
public RetryExecutor setAttemptTimeoutMillis(int v) {
timeoutMillis = v;
return this;
}

RetryExecutor setExecutorInitializer(Consumer<Executor> v) {
public RetryExecutor setExecutorInitializer(Consumer<Executor> v) {
executorInitializer = v;
return this;
}

void abort() {
public void abort() {
aborted = true;
}

boolean isAborted() {
public boolean isAborted() {
return aborted;
}

@@ -68,11 +68,11 @@ static RetryExecutor retryOnKnownErrorMessage(String v) {
});
}

void execute(String cmdline[]) throws IOException {
public void execute(String cmdline[]) throws IOException {
executeLoop(() -> Executor.of(cmdline));
}

void execute(ProcessBuilder pb) throws IOException {
public void execute(ProcessBuilder pb) throws IOException {
executeLoop(() -> Executor.of(pb));
}

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,6 +42,7 @@
import jdk.jpackage.test.Functional.ThrowingConsumer;
import jdk.jpackage.test.Functional.ThrowingSupplier;
import jdk.jpackage.test.PackageTest.PackageHandlers;
import jdk.jpackage.internal.RetryExecutor;
import org.xml.sax.SAXException;
import org.w3c.dom.NodeList;

@@ -66,11 +67,36 @@ public static void withExplodedDmg(JPackageCommand cmd,
cmd.outputBundle(), dmgImage));
ThrowingConsumer.toConsumer(consumer).accept(dmgImage);
} finally {
// detach might not work right away due to resource busy error, so
// repeat detach several times or fail. Try 10 times with 3 seconds
// delay.
Executor.of("/usr/bin/hdiutil", "detach").addArgument(mountPoint).
executeAndRepeatUntilExitCode(0, 10, 3);
String cmdline[] = {
"/usr/bin/hdiutil",
"detach",
"-verbose",
mountPoint.toAbsolutePath().toString()};
// "hdiutil detach" might not work right away due to resource busy error, so
// repeat detach several times.
RetryExecutor retryExecutor = new RetryExecutor();
// Image can get detach even if we got resource busy error, so stop
// trying to detach it if it is no longer attached.
retryExecutor.setExecutorInitializer(exec -> {
if (!Files.exists(mountPoint)) {
retryExecutor.abort();
}
});
try {
// 10 times with 6 second delays.
retryExecutor.setMaxAttemptsCount(10)
.setAttemptTimeoutMillis(6000)
.execute(cmdline);
} catch (IOException ex) {
if (!retryExecutor.isAborted()) {
// Now force to detach if it still attached
if (Files.exists(mountPoint)) {
Executor.of("/usr/bin/hdiutil", "detach",
"-force", "-verbose")
.addArgument(mountPoint).execute();
}
}
}
}
}

0 comments on commit bec6043

Please sign in to comment.