All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zeroturnaround.process.ProcessUtil Maven / Gradle / Ivy

There is a newer version: 1.11
Show newest version
package org.zeroturnaround.process;

import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Additional helper methods for killing processes and waiting until they finish.
 * 
 * Here all methods that use a timeout throw {@link TimeoutException} including the given timeout in the message
 * instead of returning a false like {@link SystemProcess} does.
 * Also all methods log a message in case the operation succeeded including the time it took.
 * 

* Notice that methods that destroy a process do not include destroying operation itself in the timeout period. They start measuring time after sending the destroy signal. * Also if the current thread is interrupted it may also interrupt sending the destroy signal itself not just the waiting period after it. So if the current thread gets * interrupted there's no guarantee that the target process actually got signaled. * * @see SystemProcess */ public class ProcessUtil { private static final Logger log = LoggerFactory.getLogger(ProcessUtil.class); /** * Waits until the given process finishes or the current thread is interrupted. * * @param process the target process. * * @throws InterruptedException if the current thread was interrupted. */ public static void waitFor(SystemProcess process) throws InterruptedException { log.info("Waiting for {} to finish.", process); waitFor(process, Stopwatch.createStarted(), "{} finished"); } /** * Waits until the given process finishes, a timeout is reached or the current thread is interrupted. * * @param process the target process. * @param timeout the maximum time to wait until the process finishes. * @param unit the time unit of the timeout argument. * * @throws InterruptedException if the current thread was interrupted. * @throws TimeoutException if timeout was reached before the process finished. */ public static void waitFor(SystemProcess process, long timeout, TimeUnit unit) throws InterruptedException, TimeoutException { log.info("Waiting for {} to finish.", process); waitFor(process, Stopwatch.createStarted(), timeout, unit, "{} finished", "%s did not finish"); } /** * Destroys the given process gracefully and waits until it finishes or the current thread is interrupted. * * @param process the target process. * * @throws InterruptedException if the current thread was interrupted. */ public static void destroyGracefullyAndWait(SystemProcess process) throws IOException, InterruptedException { Stopwatch sw = Stopwatch.createStarted(); process.destroyGracefully(); waitFor(process, sw, "Destroyed {} gracefully"); } /** * Destroys the given process gracefully and waits until it finishes, a timeout occurs or the current thread is interrupted. * * @param process the target process. * @param timeout the maximum time to wait until the process finishes. * @param unit the time unit of the timeout argument. * * @throws InterruptedException if the current thread was interrupted. * @throws TimeoutException if timeout was reached before the process finished. */ public static void destroyGracefullyAndWait(SystemProcess process, long timeout, TimeUnit unit) throws IOException, InterruptedException, TimeoutException { Stopwatch sw = Stopwatch.createStarted(); process.destroyGracefully(); waitFor(process, sw, timeout, unit, "Destroyed {} gracefully", "Could not destroy %s gracefully"); } /** * Destroys the given process forcefully and waits until it finishes or the current thread is interrupted. * * @param process the target process. * * @throws InterruptedException if the current thread was interrupted. */ public static void destroyForcefullyAndWait(SystemProcess process) throws IOException, InterruptedException { Stopwatch sw = Stopwatch.createStarted(); process.destroyForcefully(); waitFor(process, sw, "Destroyed {} forcefully"); } /** * Destroys the given process forcefully and waits until it finishes, a timeout occurs or the current thread is interrupted. * * @param process the target process. * @param timeout the maximum time to wait until the process finishes. * @param unit the time unit of the timeout argument. * * @throws InterruptedException if the current thread was interrupted. * @throws TimeoutException if timeout was reached before the process finished. */ public static void destroyForcefullyAndWait(SystemProcess process, long timeout, TimeUnit unit) throws IOException, InterruptedException, TimeoutException { Stopwatch sw = Stopwatch.createStarted(); process.destroyForcefully(); waitFor(process, sw, timeout, unit, "Destroyed {} forcefully", "Could not destroy %s forcefully"); } /** * Destroys the given process gracefully and waits until it finishes or the current thread is interrupted. * If the graceful destroy operation throws an exception (e.g. it's unsupported) * it destroys the process forcefully and waits until it finishes or the current thread is interrupted. * * @param process the target process. * * @throws InterruptedException if the current thread was interrupted. */ public static void destroyGracefullyOrForcefullyAndWait(SystemProcess process) throws IOException, InterruptedException { try { destroyGracefullyAndWait(process); return; } catch (UnsupportedOperationException e) { log.trace("Destroying {} gracefully is unsupported, trying forcefully:", process); } catch (Exception e) { log.error("Could not destroy {} gracefully, trying forcefully:", process, e); } destroyForcefullyAndWait(process); } /** * Destroys the given process gracefully and waits until it finishes, a timeout occurs or the current thread is interrupted. * If the graceful destroy operation throws an exception (e.g. it's unsupported) or a timeout is reached * it destroys the process forcefully and waits until it finishes or the current thread is interrupted (no timeout is used in this case). * * @param process the target process. * @param timeout the maximum time to wait until the process finishes after the graceful destroy operation. * @param unit the time unit of the timeout argument. * * @throws InterruptedException if the current thread was interrupted. */ public static void destroyGracefullyOrForcefullyAndWait(SystemProcess process, long gracefulTimeout, TimeUnit gracefulTimeoutUnit) throws IOException, InterruptedException { if (tryDestroyGracefully(process, gracefulTimeout, gracefulTimeoutUnit)) { return; } destroyForcefullyAndWait(process); } /** * Destroys the given process gracefully and waits until it finishes, first timeout occurs or the current thread is interrupted. * If the graceful destroy operation throws an exception (e.g. it's unsupported) or a timeout is reached * it destroys the process forcefully and waits until it finishes, second timeout occurs or the current thread is interrupted. * * @param process the target process. * @param gracefulTimeout the maximum time to wait until the process finishes after the graceful destroy operation. * @param gracefulTimeoutUnit the time unit of the gracefulTimeout argument. * @param forcefulTimeout the maximum time to wait until the process finishes after the forceful destroy operation. * @param forcefulTimeoutUnit the time unit of the forcefulTimeout argument. * * @throws InterruptedException if the current thread was interrupted. * @throws TimeoutException if timeout was reached before the process finished (after the forceful destroy operation). */ public static void destroyGracefullyOrForcefullyAndWait(SystemProcess process, long gracefulTimeout, TimeUnit gracefulTimeoutUnit, long forcefulTimeout, TimeUnit forcefulTimeoutUnit) throws IOException, InterruptedException, TimeoutException { if (tryDestroyGracefully(process, gracefulTimeout, gracefulTimeoutUnit)) { return; } destroyForcefullyAndWait(process, forcefulTimeout, forcefulTimeoutUnit); } private static boolean tryDestroyGracefully(SystemProcess killer, long gracefulTimeout, TimeUnit gracefulTimeoutUnit) { try { destroyGracefullyAndWait(killer, gracefulTimeout, gracefulTimeoutUnit); return true; } catch (UnsupportedOperationException e) { log.trace("Destroying {} gracefully is unsupported, trying forcefully:", killer); } catch (TimeoutException e) { log.info(e.getMessage() + ", trying forcefully."); } catch (Exception e) { log.error("Could not destroy {} gracefully, trying forcefully.", killer, e); } return false; } /** * Waits until the given process finishes or the current thread is interrupted. * * @param process the target process. * @param sw stopwatch started before the main operation. * @param successFormat format for logging a message after the process has finished, including single {} as the process description placeholder, * e.g. "Process {} finished". * * @throws InterruptedException if the current thread was interrupted. */ private static void waitFor(SystemProcess process, Stopwatch sw, String successFormat) throws InterruptedException { process.waitFor(); long duration = sw.stop().elapsed(TimeUnit.MILLISECONDS); log.info(successFormat + " in {} ms.", process, duration); } /** * Waits until the given process finishes, a timeout occurs or the current thread is interrupted. * * @param process the target process. * @param sw stopwatch started before the main operation. * @param timeout the maximum time to wait until the process finishes. * @param unit the time unit of the timeout argument. * @param successFormat format for logging a message after the process has finished, including single {} as the process description placeholder, * e.g. "Process {} finished". * @param timeoutFormat format for the error message after the timeout is reached, including single %s as the process description placeholder, * e.g. "Process %s did not finish" * * @throws InterruptedException if the current thread was interrupted. */ private static void waitFor(SystemProcess process, Stopwatch sw, long timeout, TimeUnit unit, String successFormat, String timeoutFormat) throws InterruptedException, TimeoutException { if (!process.waitFor(timeout, unit)) { throw new TimeoutException(String.format(timeoutFormat + " in %d %s", process, timeout, unit.toString().toLowerCase())); } long duration = sw.stop().elapsed(TimeUnit.MILLISECONDS); log.info(successFormat + " in {} ms.", process, duration); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy