Refactor the ProcessWrapper.shutdown() method.

* Removes the use of the now deprecated signalStop() method.
* Changes safeGetPid() to handle all Throwable objects.
* Changes shutdown() to call stop() and then forcibly destroy the child Process if the child Process is still running.
* Annotates the API with Spring's @NonNull and @Nullable annotations.
* Edits Javadoc.
This commit is contained in:
John Blum
2022-10-17 10:02:34 -07:00
parent b6d043ae14
commit b81c00acec
3 changed files with 18 additions and 15 deletions

View File

@@ -133,7 +133,7 @@ public abstract class ProcessExecutor {
ProcessWrapper processWrapper = new ProcessWrapper(process, ProcessConfiguration.create(processBuilder));
processWrapper.register((input) -> System.err.printf("[FORK] - %s%n", input));
processWrapper.register(input -> System.err.printf("[FORK] - %s%n", input));
processWrapper.registerShutdownHook();
return processWrapper;

View File

@@ -36,11 +36,11 @@ import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* The {@link ProcessUtils} class is a utility class for working with Operating System (OS) {@link Process processes}.
* Abstract utility class for processing Operating System (OS) {@link Process processes}.
*
* @author John Blum
* @see File
* @see Process
* @see java.io.File
* @see java.lang.Process
* @since 0.0.1
*/
@SuppressWarnings("unused")
@@ -50,7 +50,6 @@ public abstract class ProcessUtils {
protected static final String TERM_TOKEN = "<TERM/>";
/* (non-Javadoc) */
public static int currentPid() {
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();

View File

@@ -39,6 +39,7 @@ import org.springframework.data.gemfire.tests.util.FileUtils;
import org.springframework.data.gemfire.tests.util.IOUtils;
import org.springframework.data.gemfire.tests.util.ThreadUtils;
import org.springframework.data.gemfire.tests.util.ThrowableUtils;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -83,7 +84,7 @@ public class ProcessWrapper {
private String host = DEFAULT_HOST;
public ProcessWrapper(Process process, ProcessConfiguration processConfiguration) {
public ProcessWrapper(@NonNull Process process, @NonNull ProcessConfiguration processConfiguration) {
Assert.notNull(process, "Process is required");
@@ -134,7 +135,7 @@ public class ProcessWrapper {
};
}
private Thread newThread(String name, Runnable task) {
private @NonNull Thread newThread(@NonNull String name, @NonNull Runnable task) {
Assert.hasText(name, "Thread name is required");
Assert.notNull(task, "Thread task is required");
@@ -279,6 +280,7 @@ public class ProcessWrapper {
}
}
@Deprecated
public void signalStop() {
try {
@@ -305,7 +307,8 @@ public class ProcessWrapper {
boolean interrupted = false;
int exitValue = -1;
int pid = safeGetPid();
long timeout = (System.currentTimeMillis() + milliseconds);
long timeout = System.currentTimeMillis() + milliseconds;
AtomicBoolean exited = new AtomicBoolean(false);
ExecutorService executorService = Executors.newSingleThreadExecutor();
@@ -330,9 +333,7 @@ public class ProcessWrapper {
}
}
catch (TimeoutException cause) {
exitValue = -1;
this.log.warning(String.format("Process [%1$d] did not stop within the allotted timeout of %2$d seconds%n",
pid, TimeUnit.MILLISECONDS.toSeconds(milliseconds)));
}
@@ -341,7 +342,6 @@ public class ProcessWrapper {
}
finally {
executorService.shutdownNow();
if (interrupted) {
Thread.currentThread().interrupt();
}
@@ -356,13 +356,17 @@ public class ProcessWrapper {
public int shutdown() {
int pid = safeGetPid();
this.log.info(String.format("Stopping process [%d]...%n", pid));
if (isRunning()) {
this.log.info(String.format("Stopping process [%d]...%n", safeGetPid()));
signalStop();
waitFor();
stop();
if (isRunning()) {
this.process.destroyForcibly();
}
}
return stop();
return safeExitValue();
}
public boolean unregister(ProcessInputStreamListener listener) {