Skip to content

Commit

Permalink
Make running of stat command more robust.
Browse files Browse the repository at this point in the history
  • Loading branch information
raphw committed Jul 11, 2019
1 parent 1e60bd0 commit b204feb
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -352,20 +352,21 @@ public Connection connect(String processId) throws IOException {
// The HotSpot attachment API attempts to send the signal to all children of a process
Process process = Runtime.getRuntime().exec("kill -3 " + processId);
int attempts = this.attempts;
boolean killed = false;
boolean exited = false;
do {
try {
if (process.exitValue() != 0) {
throw new IllegalStateException("Error while sending signal to target VM: " + processId);
}
killed = true;
exited = true;
break;
} catch (IllegalThreadStateException ignored) {
attempts -= 1;
Thread.sleep(timeUnit.toMillis(pause));
}
} while (attempts > 0);
if (!killed) {
if (!exited) {
process.destroy();
throw new IllegalStateException("Target VM did not respond to signal: " + processId);
}
attempts = this.attempts;
Expand Down Expand Up @@ -617,7 +618,7 @@ protected ForOpenJ9(Socket socket) {
* @throws IOException If an IO exception occurs during establishing the connection.
*/
public static VirtualMachine attach(String processId) throws IOException {
return attach(processId, 5000, new Connector.ForJnaPosixEnvironment());
return attach(processId, 5000, new Connector.ForJnaPosixEnvironment(15, 100, TimeUnit.MILLISECONDS));
}

/**
Expand Down Expand Up @@ -941,6 +942,34 @@ class ForJnaPosixEnvironment implements Connector {
*/
private final PosixLibrary library = Native.load("c", PosixLibrary.class);

/**
* The maximum amount of attempts for checking the result of a foreign process.
*/
private final int attempts;

/**
* The pause between two checks for another process to return.
*/
private final long pause;

/**
* The time unit of the pause time.
*/
private final TimeUnit timeUnit;

/**
* Creates a new connector for a POSIX enviornment using JNA.
*
* @param attempts The maximum amount of attempts for checking the result of a foreign process.
* @param pause The pause between two checks for another process to return.
* @param timeUnit The time unit of the pause time.
*/
public ForJnaPosixEnvironment(int attempts, long pause, TimeUnit timeUnit) {
this.attempts = attempts;
this.pause = pause;
this.timeUnit = timeUnit;
}

/**
* {@inheritDoc}
*/
Expand Down Expand Up @@ -976,16 +1005,30 @@ public boolean isExistingProcess(long processId) {
public long getOwnerIdOf(File file) {
try {
Process process = Runtime.getRuntime().exec("stat -c=%u " + file.getAbsolutePath());
try {
String line = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8")).readLine();
if (process.exitValue() != 0) {
throw new IllegalStateException("Unexpected return by stat command: " + line);
int attempts = this.attempts;
boolean exited = false;
String line = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8")).readLine();
do {
try {
if (process.exitValue() != 0) {
throw new IllegalStateException("Error while executing stat");
}
exited = true;
break;
} catch (IllegalThreadStateException ignored) {
try {
Thread.sleep(timeUnit.toMillis(pause));
} catch (InterruptedException exception) {
Thread.currentThread().interrupt();
throw new IllegalStateException("Interrupted while waiting for stat", exception);
}
}
return Long.parseLong(line.substring(1));
} catch (IOException exception) {
} while (--attempts > 0);
if (!exited) {
process.destroy();
throw exception;
throw new IllegalStateException("Command for stat did not exit in time");
}
return Long.parseLong(line.substring(1));
} catch (IOException exception) {
throw new IllegalStateException("Unable to execute stat command", exception);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public void tearDown() throws Exception {

@Test
@UnixRule.Enforce
public void canAttachViaPosixSocket() throws Exception {
public void testAttachment() throws Exception {
assertThat(SampleAgent.argument, nullValue(String.class));
VirtualMachine virtualMachine = (VirtualMachine) VirtualMachine.Resolver.INSTANCE.run()
.getMethod("attach", String.class)
Expand Down

0 comments on commit b204feb

Please sign in to comment.