Detect process third party audit being killed by OOM (#44269)

* Detect process third party audit being killed by OOM

It's very common for the third party audit to be killed by the OOM
killer when the system is running low on memory.
Since the forbidden APIs call is expected to fail, we were ignoring
these and incorrectly interpreting the partial output.
With this change we detect and provide a proper error message when this
happens.
This commit is contained in:
Alpar Torok 2019-07-18 10:00:19 +03:00
parent 6565825a13
commit 9f97319b3c
2 changed files with 20 additions and 22 deletions

View File

@ -18,8 +18,10 @@
*/
package org.elasticsearch.gradle.precommit;
import de.thetaphi.forbiddenapis.cli.CliMain;
import org.apache.commons.io.output.NullOutputStream;
import org.elasticsearch.gradle.JdkJarHellCheck;
import org.elasticsearch.gradle.OS;
import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
import org.gradle.api.JavaVersion;
@ -51,6 +53,7 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
@ -69,6 +72,12 @@ public class ThirdPartyAuditTask extends DefaultTask {
private static final Pattern VIOLATION_PATTERN = Pattern.compile(
"\\s\\sin ([a-zA-Z0-9$.]+) \\(.*\\)"
);
private static final int SIG_KILL_EXIT_VALUE = 137;
private static final List<Integer> EXPECTED_EXIT_CODES = Arrays.asList(
CliMain.EXIT_SUCCESS,
CliMain.EXIT_VIOLATION,
CliMain.EXIT_UNSUPPORTED_JDK
);
private Set<String> missingClassExcludes = new TreeSet<>();
@ -327,7 +336,7 @@ public class ThirdPartyAuditTask extends DefaultTask {
private String runForbiddenAPIsCli() throws IOException {
ByteArrayOutputStream errorOut = new ByteArrayOutputStream();
getProject().javaexec(spec -> {
ExecResult result = getProject().javaexec(spec -> {
if (javaHome != null) {
spec.setExecutable(javaHome + "/bin/java");
}
@ -336,6 +345,7 @@ public class ThirdPartyAuditTask extends DefaultTask {
getRuntimeConfiguration(),
getProject().getConfigurations().getByName("compileOnly")
);
spec.jvmArgs("-Xmx1g");
spec.setMain("de.thetaphi.forbiddenapis.cli.CliMain");
spec.args(
"-f", getSignatureFile().getAbsolutePath(),
@ -348,10 +358,18 @@ public class ThirdPartyAuditTask extends DefaultTask {
}
spec.setIgnoreExitValue(true);
});
if (OS.current().equals(OS.LINUX) && result.getExitValue() == SIG_KILL_EXIT_VALUE) {
throw new IllegalStateException(
"Third party audit was killed buy SIGKILL, could be a victim of the Linux OOM killer"
);
}
final String forbiddenApisOutput;
try (ByteArrayOutputStream outputStream = errorOut) {
forbiddenApisOutput = outputStream.toString(StandardCharsets.UTF_8.name());
}
if (EXPECTED_EXIT_CODES.contains(result.getExitValue()) == false) {
throw new IllegalStateException("Forbidden APIs cli failed: " + forbiddenApisOutput);
}
return forbiddenApisOutput;
}

View File

@ -48,27 +48,7 @@ public class ThirdPartyAuditTaskIT extends GradleIntegrationTestCase {
"-PcompileOnlyGroup=other.gradle:broken-log4j", "-PcompileOnlyVersion=0.0.1",
"-PcompileGroup=other.gradle:dummy-io", "-PcompileVersion=0.0.1"
)
.build();
assertTaskSuccessful(result, ":empty");
result = getGradleRunner("thirdPartyAudit")
.withArguments("empty", "-s",
"-PcompileOnlyGroup=other.gradle:broken-log4j", "-PcompileOnlyVersion=0.0.1",
"-PcompileGroup=other.gradle:dummy-io", "-PcompileVersion=0.0.1"
)
.build();
assertTaskUpToDate(result, ":empty");
result = getGradleRunner("thirdPartyAudit")
.withArguments("empty", "-s",
"-PcompileOnlyGroup=other.gradle:broken-log4j", "-PcompileOnlyVersion=0.0.1",
"-PcompileGroup=other.gradle:dummy-io", "-PcompileVersion=0.0.2"
)
.build();
assertTaskSuccessful(result, ":empty");
.buildAndFail();
}
public void testViolationFoundAndCompileOnlyIgnored() {