0

In the code snippet provided below a new process is started from Java. The new process is a shell that starts some Linux utilities. The problem I have is that 'atop' and 'awk' utilities are still running after calling process.destroy(). I have tried process.destroyForcibly() but no improvements. The variable continueMonitoring is updated from a different thread.

Question destroy all proceses does not address the problem of stooping processes that use pipe mechanism between them, in my case I don't even have the PIDs for all the processes that are started.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;

public class MinimalClient {
    boolean continueMonitoring = true;

    public static void main(String[] args) throws InterruptedException {
        MinimalClient mc = new MinimalClient();
        mc.startMonitoring();
    }


    public void startMonitoring() throws InterruptedException {
        Thread cpuMonit = new Thread(new Runnable() {
            @Override
            public void run() {
                String line;
                Process process;
                StringBuilder commandOutput = new StringBuilder();

                String processPid = getPid();
                String[] cmd = {
                        "/bin/sh",
                        "-c",
                        " atop 1 -a | unbuffer -p awk '/" + processPid + "|nmap/ {print $1 \" \" $11}'"
                };

                try {
                    process = Runtime.getRuntime().exec(cmd);
                    Field pid = process.getClass().getDeclaredField("pid");
                    pid.setAccessible(true);
                    BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));

                    while ( continueMonitoring && (line = br.readLine()) != null) {
                        commandOutput.append(line + "\n");
                    }
                    process.destroy();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                }

            }
        });
        cpuMonit.start();
        Thread.sleep(10000);
        continueMonitoring = false;
    }

    private String getPid() {
        String processName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
        return processName.split("@")[0];
    }
}
Community
  • 1
  • 1
bogconst
  • 33
  • 1
  • 7
  • Are the processes "defunct" (zombie) in the process table? – Damien O'Reilly Sep 10 '15 at 16:20
  • 1
    Are you blocking the current thread by reading from streams, and thus are not able to reach the `process.destroy()` line? You don't address this. – Hovercraft Full Of Eels Sep 10 '15 at 16:22
  • @DamienO'Reilly they don't seem to be defunct, for example atop consumes around 7% CPU. – bogconst Sep 10 '15 at 16:27
  • @user3619884 I think you should look at [ProcessBuilder](http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html). Take a look here: http://stackoverflow.com/a/17771260/3899529 – Damien O'Reilly Sep 10 '15 at 16:33
  • @HovercraftFullOfEels I have updated the question. The 'process.destroy()' method is called. – bogconst Sep 10 '15 at 16:37
  • @user3619884: no it's not. You've ignored the most important part of my comment -- are you using a background thread to avoid blocking the current thread, and you appear not to be doing this? It looks like you're blocking the thread meaning destroy likely will never be called. Please re-address the threading issue -- don't ignore this part of my request. – Hovercraft Full Of Eels Sep 10 '15 at 16:39
  • @HovercraftFullOfEels I wrote in the initial question that I use a different thread to update `continueMonitoring` variable. I have checked with the debugger and 'process.destroy()' is called. – bogconst Sep 10 '15 at 16:45
  • Let's see your [mcve] to remove all doubt. – Hovercraft Full Of Eels Sep 10 '15 at 16:51
  • @HovercraftFullOfEels I have provided a minimal example that can be run directly on any Linux machine that has 'atop' and 'unbuffer' installed. – bogconst Sep 10 '15 at 17:24
  • `continueMonitoring` needs to be declared `volatile`, or changes made by one thread may not be seen by other threads. See [this section of the Java Language Specification](http://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.3) for a good explanation. – VGR Sep 10 '15 at 17:57
  • @VGR adding 'volatile' does not help solve the problem. – bogconst Sep 10 '15 at 19:57

0 Answers0