Search in sources :

Example 1 with PidProcess

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();
}
Also used : WindowsProcess(org.zeroturnaround.process.WindowsProcess) PidProcess(org.zeroturnaround.process.PidProcess) InvalidExitValueException(org.zeroturnaround.exec.InvalidExitValueException)

Example 2 with PidProcess

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;
}
Also used : PidProcess(org.zeroturnaround.process.PidProcess)

Example 3 with PidProcess

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) {
        }
    }
}
Also used : Platform(com.aws.greengrass.util.platforms.Platform) PidProcess(org.zeroturnaround.process.PidProcess) PidProcess(org.zeroturnaround.process.PidProcess) IOException(java.io.IOException)

Example 4 with PidProcess

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());
    }
}
Also used : PidProcess(org.zeroturnaround.process.PidProcess) InputStreamReader(java.io.InputStreamReader) Matcher(java.util.regex.Matcher) PidProcess(org.zeroturnaround.process.PidProcess) IOException(java.io.IOException) Utils.inputStreamToString(com.aws.greengrass.util.Utils.inputStreamToString) BufferedReader(java.io.BufferedReader) ArrayList(java.util.ArrayList) List(java.util.List) Pair(com.aws.greengrass.util.Pair)

Aggregations

PidProcess (org.zeroturnaround.process.PidProcess)4 IOException (java.io.IOException)2 Pair (com.aws.greengrass.util.Pair)1 Utils.inputStreamToString (com.aws.greengrass.util.Utils.inputStreamToString)1 Platform (com.aws.greengrass.util.platforms.Platform)1 BufferedReader (java.io.BufferedReader)1 InputStreamReader (java.io.InputStreamReader)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 Matcher (java.util.regex.Matcher)1 InvalidExitValueException (org.zeroturnaround.exec.InvalidExitValueException)1 WindowsProcess (org.zeroturnaround.process.WindowsProcess)1