You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by vl...@apache.org on 2019/10/19 21:54:49 UTC
[jmeter] branch master updated: Rework SystemCommand and OS Process
Sampler: avoid throwing InterruptedException on timeout
This is an automated email from the ASF dual-hosted git repository.
vladimirsitnikov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jmeter.git
The following commit(s) were added to refs/heads/master by this push:
new 75011a5 Rework SystemCommand and OS Process Sampler: avoid throwing InterruptedException on timeout
75011a5 is described below
commit 75011a5f91ab89c1fcba31348d1428cdea0ad6b1
Author: Vladimir Sitnikov <si...@gmail.com>
AuthorDate: Sat Oct 19 23:37:53 2019 +0300
Rework SystemCommand and OS Process Sampler: avoid throwing InterruptedException on timeout
"os command" timeout should not cause thread re-interrupt, so new InterruptedException() pattern should not be used
---
bin/testfiles/OS_TESTS.csv | 2 +-
bin/testfiles/OS_TESTS.jmx | 4 +-
bin/testfiles/OS_TESTS.xml | 2 +-
.../src/main/java/org/apache/jmeter/JMeter.java | 4 +-
.../jmeter/gui/action/HtmlReportGenerator.java | 6 ++-
.../java/org/apache/jorphan/exec/KeyToolUtils.java | 11 ++++++
.../org/apache/jorphan/exec/SystemCommand.java | 43 ++++++++++------------
.../jmeter/protocol/system/SystemSampler.java | 11 ++++--
xdocs/usermanual/properties_reference.xml | 7 ----
9 files changed, 48 insertions(+), 42 deletions(-)
diff --git a/bin/testfiles/OS_TESTS.csv b/bin/testfiles/OS_TESTS.csv
index c180fc4..8f0b59b 100644
--- a/bin/testfiles/OS_TESTS.csv
+++ b/bin/testfiles/OS_TESTS.csv
@@ -1,4 +1,4 @@
label,responseCode,responseMessage,threadName,dataType,success,grpThreads,allThreads,SampleCount,ErrorCount
OSPS-listDirectory,0,OK,Thread Group 1-1,text,true,1,1,1,0
OSPS-listEnv,0,OK,Thread Group 1-1,text,true,1,1,1,0
-OSPS-sleep,500,System Sampler interrupted whilst executing system call: java.lang.InterruptedException: Process timeout out after 1000 milliseconds,Thread Group 1-1,text,true,1,1,1,0
+OSPS-sleep,500,Process timeout reached after 1000 milliseconds,Thread Group 1-1,text,true,1,1,1,0
diff --git a/bin/testfiles/OS_TESTS.jmx b/bin/testfiles/OS_TESTS.jmx
index 65f0c87..e032a3a 100644
--- a/bin/testfiles/OS_TESTS.jmx
+++ b/bin/testfiles/OS_TESTS.jmx
@@ -136,7 +136,7 @@
<hashTree>
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true">
<collectionProp name="Asserion.test_strings">
- <stringProp name="-57279347">Process timeout out after 1000 milliseconds</stringProp>
+ <stringProp name="-57279347">Process timeout reached after 1000 milliseconds</stringProp>
</collectionProp>
<stringProp name="Assertion.test_field">Assertion.response_message</stringProp>
<boolProp name="Assertion.assume_success">true</boolProp>
@@ -293,7 +293,7 @@
<hashTree>
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true">
<collectionProp name="Asserion.test_strings">
- <stringProp name="-57279347">Process timeout out after 1000 milliseconds</stringProp>
+ <stringProp name="-57279347">Process timeout reached after 1000 milliseconds</stringProp>
</collectionProp>
<stringProp name="Assertion.test_field">Assertion.response_message</stringProp>
<boolProp name="Assertion.assume_success">true</boolProp>
diff --git a/bin/testfiles/OS_TESTS.xml b/bin/testfiles/OS_TESTS.xml
index 49171ff..fecf861 100644
--- a/bin/testfiles/OS_TESTS.xml
+++ b/bin/testfiles/OS_TESTS.xml
@@ -19,7 +19,7 @@
<error>false</error>
</assertionResult>
</sample>
-<sample s="true" lb="OSPS-sleep" rc="500" rm="System Sampler interrupted whilst executing system call: java.lang.InterruptedException: Process timeout out after 1000 milliseconds" tn="Thread Group 1-1" dt="text" sc="1" ec="0" ng="1" na="1">
+<sample s="true" lb="OSPS-sleep" rc="500" rm="Process timeout reached after 1000 milliseconds" tn="Thread Group 1-1" dt="text" sc="1" ec="0" ng="1" na="1">
<assertionResult>
<name>Response Assertion</name>
<failure>false</failure>
diff --git a/src/core/src/main/java/org/apache/jmeter/JMeter.java b/src/core/src/main/java/org/apache/jmeter/JMeter.java
index 6113836..7fcf271 100644
--- a/src/core/src/main/java/org/apache/jmeter/JMeter.java
+++ b/src/core/src/main/java/org/apache/jmeter/JMeter.java
@@ -463,8 +463,8 @@ public class JMeter implements JMeterPlugin {
Thread.setDefaultUncaughtExceptionHandler(
(Thread t, Throwable e) -> {
if (!(e instanceof ThreadDeath)) {
- log.error("Uncaught exception: ", e);
- System.err.println("Uncaught Exception " + e + ". See log file for details.");//NOSONAR
+ log.error("Uncaught exception in thread " + t, e);
+ System.err.println("Uncaught Exception " + e + " in thread " + t + ". See log file for details.");//NOSONAR
}
});
diff --git a/src/core/src/main/java/org/apache/jmeter/gui/action/HtmlReportGenerator.java b/src/core/src/main/java/org/apache/jmeter/gui/action/HtmlReportGenerator.java
index b781270..6035e51 100644
--- a/src/core/src/main/java/org/apache/jmeter/gui/action/HtmlReportGenerator.java
+++ b/src/core/src/main/java/org/apache/jmeter/gui/action/HtmlReportGenerator.java
@@ -24,6 +24,7 @@ import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.TimeoutException;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.exec.SystemCommand;
@@ -87,9 +88,12 @@ public class HtmlReportGenerator {
LOGGER.info("The HTML report generation failed and returned: {}", commandExecutionOutput);
return errorMessageList;
}
- } catch (InterruptedException | IOException e) {
+ } catch (InterruptedException | TimeoutException | IOException e) {
errorMessageList.add(commandExecutionOutput.toString());
LOGGER.error("Error during HTML report generation:", e);
+ if (e instanceof InterruptedException) {
+ Thread.currentThread().interrupt();
+ }
}
LOGGER.debug("SystemCommand ran: {} returned: {}", generationCommand, resultCode);
return errorMessageList;
diff --git a/src/jorphan/src/main/java/org/apache/jorphan/exec/KeyToolUtils.java b/src/jorphan/src/main/java/org/apache/jorphan/exec/KeyToolUtils.java
index df8d63c..679e72d 100644
--- a/src/jorphan/src/main/java/org/apache/jorphan/exec/KeyToolUtils.java
+++ b/src/jorphan/src/main/java/org/apache/jorphan/exec/KeyToolUtils.java
@@ -27,6 +27,7 @@ import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.TimeoutException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.SystemUtils;
@@ -173,7 +174,10 @@ public class KeyToolUtils {
+ "\n'" + formatCommand(arguments)+"'");
}
} catch (InterruptedException e) { // NOSONAR
+ Thread.currentThread().interrupt();
throw new IOException("Command was interrupted\n" + nativeCommand.getOutResult(), e);
+ } catch (TimeoutException e) { // NOSONAR
+ throw new IOException("Timeout reached while executing\n" + nativeCommand.getOutResult(), e);
}
}
@@ -369,7 +373,10 @@ public class KeyToolUtils {
throw new IOException("Command failed, code: " + exitVal + "\n" + nativeCommand.getOutResult());
}
} catch (InterruptedException e) { // NOSONAR
+ Thread.currentThread().interrupt();
throw new IOException("Command was interrupted\n" + nativeCommand.getOutResult(), e);
+ } catch (TimeoutException e) { // NOSONAR
+ throw new IOException("Timeout reached while executing\n" + nativeCommand.getOutResult(), e);
}
}
@@ -480,6 +487,10 @@ public class KeyToolUtils {
return false;
} catch (InterruptedException e) { // NOSONAR
log.error("Command was interrupted\n" + nativeCommand.getOutResult(), e);
+ Thread.currentThread().interrupt();
+ return false;
+ } catch (TimeoutException e) { // NOSONAR
+ log.info("Timeout reached while checking for keytool existence, will return false, try another way.", e);
return false;
}
}
diff --git a/src/jorphan/src/main/java/org/apache/jorphan/exec/SystemCommand.java b/src/jorphan/src/main/java/org/apache/jorphan/exec/SystemCommand.java
index ca58c00..1814edc 100644
--- a/src/jorphan/src/main/java/org/apache/jorphan/exec/SystemCommand.java
+++ b/src/jorphan/src/main/java/org/apache/jorphan/exec/SystemCommand.java
@@ -30,6 +30,8 @@ import java.io.OutputStream;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import org.apache.jorphan.util.JOrphanUtils;
@@ -37,6 +39,10 @@ import org.apache.jorphan.util.JOrphanUtils;
* Utility class for invoking native system applications
*/
public class SystemCommand {
+ /**
+ * @deprecated does not make sense anymore. Superceded by {@link Process#wait(long)}
+ */
+ @Deprecated
public static final int POLL_INTERVAL = 100;
private final File directory;
private final Map<String, String> env;
@@ -53,7 +59,7 @@ public class SystemCommand {
* @param directory File working directory (may be null)
*/
public SystemCommand(File directory, Map<String, String> env) {
- this(directory, 0L, POLL_INTERVAL, env, (InputStream) null, (OutputStream) null, (OutputStream) null);
+ this(directory, 0L, 0, env, (InputStream) null, (OutputStream) null, (OutputStream) null);
}
/**
@@ -123,13 +129,13 @@ public class SystemCommand {
* @throws InterruptedException when execution was interrupted
* @throws IOException when I/O error occurs while execution
*/
- public int run(List<String> arguments) throws InterruptedException, IOException {
+ public int run(List<String> arguments) throws InterruptedException, IOException, TimeoutException {
return run(arguments, stdin, stdout, stderr);
}
// helper method to allow input and output to be changed for chaining
private int run(List<String> arguments, InputStream in,
- OutputStream out,OutputStream err) throws InterruptedException, IOException {
+ OutputStream out,OutputStream err) throws InterruptedException, IOException, TimeoutException {
Process proc = null;
final ProcessBuilder procBuild = new ProcessBuilder(arguments);
if (env != null) {
@@ -199,13 +205,14 @@ public class SystemCommand {
* @param arguments2 second command to run
* @return exit status
* @throws InterruptedException when execution gets interrupted
+ * @throws TimeoutException when timeout is reached while execution
* @throws IOException when I/O error occurs while execution
*/
- public int run(List<String> arguments1, List<String> arguments2) throws InterruptedException, IOException {
+ public int run(List<String> arguments1, List<String> arguments2) throws InterruptedException, IOException, TimeoutException {
ByteArrayOutputStream out = new ByteArrayOutputStream(); // capture the intermediate output
- int exitCode=run(arguments1,stdin,out, stderr);
+ int exitCode = run(arguments1, stdin, out, stderr);
if (exitCode == 0) {
- exitCode = run(arguments2,new ByteArrayInputStream(out.toByteArray()),stdout,stderr);
+ exitCode = run(arguments2, new ByteArrayInputStream(out.toByteArray()), stdout, stderr);
}
return exitCode;
}
@@ -215,28 +222,16 @@ public class SystemCommand {
* @param proc Process
* @param timeoutInMillis long timeout in ms
* @return proc exit value
- * @throws InterruptedException
+ * @throws TimeoutException when timeout is reached while execution
*/
- private int waitForEndWithTimeout(Process proc, long timeoutInMillis) throws InterruptedException {
+ private int waitForEndWithTimeout(Process proc, long timeoutInMillis) throws InterruptedException, TimeoutException {
if (timeoutInMillis <= 0L) {
return proc.waitFor();
- } else {
- long now = System.currentTimeMillis();
- long finish = now + timeoutInMillis;
- while(System.currentTimeMillis() < finish) {
- try {
- return proc.exitValue();
- } catch (IllegalThreadStateException e) { // not yet terminated
- Thread.sleep(pollInterval);
- }
- }
- try {
- return proc.exitValue();
- } catch (IllegalThreadStateException e) { // not yet terminated
- // N.B. proc.destroy() is called by the finally clause in the run() method
- throw new InterruptedException( "Process timeout out after " + timeoutInMillis + " milliseconds" );
- }
}
+ if (proc.waitFor(timeoutInMillis, TimeUnit.MILLISECONDS)) {
+ return proc.exitValue();
+ }
+ throw new TimeoutException("Process timeout reached after " + timeoutInMillis + " milliseconds");
}
/**
diff --git a/src/protocol/native/src/main/java/org/apache/jmeter/protocol/system/SystemSampler.java b/src/protocol/native/src/main/java/org/apache/jmeter/protocol/system/SystemSampler.java
index 1cd55de..5062537 100644
--- a/src/protocol/native/src/main/java/org/apache/jmeter/protocol/system/SystemSampler.java
+++ b/src/protocol/native/src/main/java/org/apache/jmeter/protocol/system/SystemSampler.java
@@ -27,6 +27,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.TimeoutException;
import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.config.Argument;
@@ -38,7 +39,6 @@ import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.services.FileServer;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.property.TestElementProperty;
-import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.exec.SystemCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -48,8 +48,6 @@ import org.slf4j.LoggerFactory;
*/
public class SystemSampler extends AbstractSampler {
- private static final int POLL_INTERVAL = JMeterUtils.getPropDefault("os_sampler.poll_for_timeout", SystemCommand.POLL_INTERVAL);
-
private static final long serialVersionUID = 1;
// + JMX names, do not change their values
@@ -151,7 +149,7 @@ public class SystemSampler extends AbstractSampler {
SystemCommand nativeCommand = null;
try {
- nativeCommand = new SystemCommand(directory, getTimeout(), POLL_INTERVAL, env, getStdin(), getStdout(), getStderr());
+ nativeCommand = new SystemCommand(directory, getTimeout(), 0, env, getStdin(), getStdout(), getStderr());
results.sampleStart();
int returnCode = nativeCommand.run(cmds);
results.sampleEnd();
@@ -179,6 +177,11 @@ public class SystemSampler extends AbstractSampler {
results.setResponseCode("500"); //$NON-NLS-1$
results.setResponseMessage("System Sampler interrupted whilst executing system call: " + ie);
Thread.currentThread().interrupt();
+ } catch (TimeoutException e) {
+ results.sampleEnd();
+ results.setSuccessful(false);
+ results.setResponseCode("500");
+ results.setResponseMessage(e.getMessage());
}
if (nativeCommand != null) {
diff --git a/xdocs/usermanual/properties_reference.xml b/xdocs/usermanual/properties_reference.xml
index 87994c8..e65a85f 100644
--- a/xdocs/usermanual/properties_reference.xml
+++ b/xdocs/usermanual/properties_reference.xml
@@ -1031,13 +1031,6 @@ JMETER-SERVER</source>
</properties>
</section>
<section name="§-num;.24 OS Process Sampler configuration" anchor="os_sampler">
-<properties>
-<property name="os_sampler.poll_for_timeout">
- Polling to see if process has finished its work, used when a timeout
- is configured on sampler. Specified in milliseconds.<br/>
- Defaults to: <code>100</code>
-</property>
-</properties>
</section>
<section name="§-num;.25 TCP Sampler configuration" anchor="tcp_sampler">
<properties>