diff --git a/os/src/SubProcess.scala b/os/src/SubProcess.scala index 114e9731..bbe1ede6 100644 --- a/os/src/SubProcess.scala +++ b/os/src/SubProcess.scala @@ -170,27 +170,7 @@ class SubProcess( async: Boolean = false, recursive: Boolean = true ): Unit = { - - def destroy0(p: ProcessHandle) = { - p.destroy() - if (!async) { - val now = System.currentTimeMillis() - - while ( - p.isAlive && (shutdownGracePeriod == -1 || System.currentTimeMillis() - now < shutdownGracePeriod) - ) { - Thread.sleep(1) - } - - if (p.isAlive) p.destroyForcibly() - } - } - def rec(p: ProcessHandle): Unit = { - destroy0(p) - p.children().forEach(c => rec(c)) - } - if (recursive) rec(wrapped.toHandle) - else destroy0(wrapped.toHandle) + SubProcess.destroy(wrapped.toHandle, async, shutdownGracePeriod, recursive) } @deprecated("Use destroy(shutdownGracePeriod = 0)") @@ -222,6 +202,45 @@ class SubProcess( } object SubProcess { + private def destroySingle(p: ProcessHandle, async: Boolean, shutdownGracePeriod: Long) = { + p.destroy() + if (!async) { + val now = System.currentTimeMillis() + + while ( + p.isAlive && (shutdownGracePeriod == -1 || System.currentTimeMillis() - now < shutdownGracePeriod) + ) { + Thread.sleep(1) + } + + if (p.isAlive) p.destroyForcibly() + } + } + + private def destroyRecursive( + p: ProcessHandle, + async: Boolean, + shutdownGracePeriod: Long + ): Unit = { + destroySingle(p, async, shutdownGracePeriod) + p.children().forEach(c => destroyRecursive(c, async, shutdownGracePeriod)) + + } + + /** + * Similar to [[SubProcess.destroy]], but can be called on an arbitrary process handle, + * not just [[SubProcess]] objects created by OS-Lib. e.g. could be to called on + * `ProcessHandle.current().children()` to cleanup leaked processes during shutdown + */ + def destroy( + p: ProcessHandle, + async: Boolean = false, + shutdownGracePeriod: Long = 100L, + recursive: Boolean = true + ): Unit = { + if (recursive) SubProcess.destroyRecursive(p, async, shutdownGracePeriod) + else SubProcess.destroySingle(p, async, shutdownGracePeriod) + } /** * The env passed by default to child processes.