use of org.zeroturnaround.process.PidProcess in project aws-greengrass-nucleus by aws-greengrass.
the class WindowsPlatform method killProcessAndChildren.
@Override
public Set<Integer> killProcessAndChildren(Process process, boolean force, Set<Integer> additionalPids, UserDecorator decorator) throws IOException, InterruptedException {
PidProcess pp = Processes.newPidProcess(process);
((WindowsProcess) pp).setIncludeChildren(true);
((WindowsProcess) pp).setGracefulDestroyEnabled(true);
try {
pp.destroy(force);
} catch (InvalidExitValueException e) {
// In other words, we rethrow the exception if the process is still alive.
if (process.isAlive()) {
throw e;
}
}
return Collections.emptySet();
}
use of org.zeroturnaround.process.PidProcess in project aws-greengrass-nucleus by aws-greengrass.
the class UnixPlatform method killProcessAndChildren.
@Override
public Set<Integer> killProcessAndChildren(Process process, boolean force, Set<Integer> additionalPids, UserDecorator decorator) throws IOException, InterruptedException {
PidProcess pp = Processes.newPidProcess(process);
logger.atInfo().log("Killing child processes of pid {}, force is {}", pp.getPid(), force);
Set<Integer> pids;
try {
pids = getChildPids(process);
logger.atDebug().log("Found children of {}. {}", pp.getPid(), pids);
if (additionalPids != null) {
pids.addAll(additionalPids);
}
for (Integer pid : pids) {
if (!Processes.newPidProcess(pid).isAlive()) {
continue;
}
killProcess(force, decorator, pid);
}
} finally {
// terminated immediately. This prevents the component process from shutting down gracefully.
if (force && process.isAlive()) {
process.destroyForcibly();
if (process.isAlive()) {
// Kill parent process using privileged user since the parent process might be sudo which a
// non-privileged user can't kill
killProcess(true, getUserDecorator().withUser(getPrivilegedUser()), pp.getPid());
}
}
}
return pids;
}
use of org.zeroturnaround.process.PidProcess in project aws-greengrass-nucleus by aws-greengrass.
the class UnixExec method close.
@Override
public synchronized void close() throws IOException {
if (isClosed.get()) {
return;
}
Process p = process;
if (p == null || !p.isAlive()) {
return;
}
Platform platformInstance = Platform.getInstance();
Set<Integer> pids = Collections.emptySet();
try {
pids = platformInstance.killProcessAndChildren(p, false, pids, userDecorator);
// TODO: [P41214162] configurable timeout
// Wait for it to die, but ignore the outcome and just forcefully kill it and all its
// children anyway. This way, any misbehaving children or grandchildren will be killed
// whether or not the parent behaved appropriately.
// Wait up to 5 seconds for each child process to stop
List<PidProcess> pidProcesses = pids.stream().map(Processes::newPidProcess).collect(Collectors.toList());
for (PidProcess pp : pidProcesses) {
pp.waitFor(gracefulShutdownTimeout.getSeconds(), TimeUnit.SECONDS);
}
if (pidProcesses.stream().anyMatch(pidProcess -> {
try {
return pidProcess.isAlive();
} catch (IOException ignored) {
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return false;
})) {
logger.atWarn().log("Command {} did not respond to interruption within timeout. Going to kill it now", this);
}
platformInstance.killProcessAndChildren(p, true, pids, userDecorator);
if (!p.waitFor(5, TimeUnit.SECONDS) && !isClosed.get()) {
throw new IOException("Could not stop " + this);
}
} catch (InterruptedException e) {
// If we're interrupted make sure to kill the process before returning
try {
platformInstance.killProcessAndChildren(p, true, pids, userDecorator);
} catch (InterruptedException ignore) {
}
}
}
use of org.zeroturnaround.process.PidProcess in project aws-greengrass-nucleus by aws-greengrass.
the class UnixPlatform method getChildPids.
/**
* Get the child PIDs of a process.
* @param process process
* @return a set of PIDs
* @throws IOException IO exception
* @throws InterruptedException InterruptedException
*/
public Set<Integer> getChildPids(Process process) throws IOException, InterruptedException {
PidProcess pp = Processes.newPidProcess(process);
// Use PS to list process PID and parent PID so that we can identify the process tree
logger.atDebug().log("Running ps to identify child processes of pid {}", pp.getPid());
Process proc = Runtime.getRuntime().exec(new String[] { "ps", "-ax", "-o", "pid,ppid" });
proc.waitFor();
if (proc.exitValue() != 0) {
logger.atWarn().kv("pid", pp.getPid()).kv("exit-code", proc.exitValue()).kv(STDOUT, inputStreamToString(proc.getInputStream())).kv(STDERR, inputStreamToString(proc.getErrorStream())).log("ps exited non-zero");
throw new IOException("ps exited with " + proc.exitValue());
}
try (InputStreamReader reader = new InputStreamReader(proc.getInputStream(), StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(reader)) {
Stream<String> lines = br.lines();
Map<String, String> pidToParent = lines.map(s -> {
Matcher matches = PS_PID_PATTERN.matcher(s.trim());
if (matches.matches()) {
return new Pair<>(matches.group(1), matches.group(2));
}
return null;
}).filter(Objects::nonNull).collect(Collectors.toMap(Pair::getLeft, Pair::getRight));
Map<String, List<String>> parentToChildren = Utils.inverseMap(pidToParent);
List<String> childProcesses = children(Integer.toString(pp.getPid()), parentToChildren);
return childProcesses.stream().map(Integer::parseInt).collect(Collectors.toSet());
}
}
Aggregations