How to kill a process in a Java gui which is running in a different thread?

Hi,
I have a GUI in Java. This GUI starts a process (running a perl code) in a new thread.

What I would like to do is to kill/destroy this process while it is running.

I tried the following but it didn't work:

This is how I start the process in the CheckRunner.java class . (this is not in the same thread with the gui)
mtcheck_process = mtcheck_runtime.exec(execCmd, environment);

Open in new window


In the gui thread (in the event handler), I have a event handler for a button, and when I hit this button I do this:

CheckRunner.mtcheck_process.destroy();

Open in new window


But, in the console I can still see that process is running.

How can I destroy this process so that it does not continue?
TolgarAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

mccarlIT Business Systems Analyst / Software DeveloperCommented:
Can you post the new version of the full code for CheckRunner.java?
0
TolgarAuthor Commented:
Sure.

public class CheckRunner implements Callable<List<CheckDetail>> {
    protected String resultsXML;
    protected String execCmd;
    static List<CheckDetail> checkDetails = null;
    static List<CheckDetail> checkDetailsAll = new ArrayList<CheckDetail>();
    static Process mtcheck_process = null;
    
   public void setCommand(String perlCmd)
   {
       execCmd = perlCmd;
   }
   
   public List<CheckDetail> call() {
      
     //get the environment variables
       Map<String, String> env = System.getenv();
       String [] environment = new String[env.size()];
       int i = 0;
       for (Map.Entry<String, String> entry : env.entrySet())
       {
           environment[i] = entry.getKey() + "=" + entry.getValue();
           i++;
       }
       
       Runtime mtcheck_runtime = Runtime.getRuntime();
       
       
       try {
           mtcheck_process = mtcheck_runtime.exec(execCmd, environment);
           //mtcheck_process.waitFor();
       } catch (Exception e) {
           System.out.println("error executing " + execCmd);
       }
       

       /* dump output stream */
       InputStream is = mtcheck_process.getInputStream();
       BufferedReader reader = new BufferedReader
           ( new InputStreamReader(is));
       String commandLineOutput;
       //String resultsXML = "20130717_1141_27_Mtcheck_CodingStandards_ALL_Files.xml";
       
       try {
        while ((commandLineOutput = reader.readLine()) != null) {
               //20130925_1603_28_Mwcheck_CodingStandards_ALL_Files.xml
               Pattern p = Pattern.compile("\\d{8}_\\d{4}_\\d{2}_.*?_Mtcheck_CodingStandards_ALL_Files.xml");
               Matcher m = p.matcher(commandLineOutput);
               if (m.find()){
                   resultsXML = m.group();                       
               }
               System.out.println(commandLineOutput);
           }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
       System.out.flush(); 
       //resultsXML = "20130930_1128_20_Mtcheck_CodingStandards_ALL_Files.xml";
       /* print final result of process */
       System.err.println("Exit status=" + mtcheck_process.exitValue());
       
       String tempDir = null;
       String OS = System.getProperty("os.name").toLowerCase();
       
       if (OS.indexOf("win") >= 0){
           tempDir = "C:/Temp/mtcheck";
       } else{
           tempDir = "/tmp/mtcheck";
       }
       
       //get the name of the  generated XML from the CLI 
       //and parse it to generate the results table
       String path2ResultsXML = tempDir + "/" + resultsXML;
       new ParseResultsXML().parse(path2ResultsXML);
       //checkDetails = new ParseResultsXML().getResultsXMLData();
       checkDetails = new ParseResultsXML().parse(path2ResultsXML);
       //checkDetailsAll.addAll(checkDetails);       
    //return checkDetailsAll;
       return checkDetails;
}

    public List<CheckDetail> getList()
{
    return checkDetailsAll;
}
}

Open in new window

0
TolgarAuthor Commented:
The am re-sending the last version of CheckRunner.java:

The code is:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CheckRunner implements Callable<List<CheckDetail>> {
    protected String resultsXML;
    protected String execCmd;
    static List<CheckDetail> checkDetails = null;
    final static List<CheckDetail> checkDetailsAll = new ArrayList<CheckDetail>();
    static Process mtcheck_process = null;
    
   public void setCommand(String perlCmd)
   {
       execCmd = perlCmd;
   }
   
   public List<CheckDetail> call() {
      
     //get the environment variables
       Map<String, String> env = System.getenv();
       String [] environment = new String[env.size()];
       int i = 0;
       for (Map.Entry<String, String> entry : env.entrySet())
       {
           environment[i] = entry.getKey() + "=" + entry.getValue();
           i++;
       }
       
       Runtime mtcheck_runtime = Runtime.getRuntime();
       
       
       try {
           //mtcheck_process = mtcheck_runtime.exec(execCmd, environment);
           mtcheck_process = mtcheck_runtime.exec(execCmd);
           //mtcheck_process.waitFor();
       } catch (Exception e) {
           System.out.println("error executing " + execCmd);
       }
       

       /* dump output stream */
       InputStream is = mtcheck_process.getInputStream();
       BufferedReader reader = new BufferedReader
           ( new InputStreamReader(is));
       String commandLineOutput;
       //String resultsXML = "20130717_1141_27_Mtcheck_CodingStandards_ALL_Files.xml";
       
       try {
        while ((commandLineOutput = reader.readLine()) != null) {
               //20130925_1603_28_Mtcheck_CodingStandards_ALL_Files.xml
               Pattern p = Pattern.compile("\\d{8}_\\d{4}_\\d{2}_.*?_Mtcheck_CodingStandards_ALL_Files.xml");
               Matcher m = p.matcher(commandLineOutput);
               if (m.find()){
                   resultsXML = m.group();                       
               }
               System.out.println(commandLineOutput);
           }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
       System.out.flush(); 
       //resultsXML = "20130930_1128_20_Mtcheck_CodingStandards_ALL_Files.xml";
       /* print final result of process */
       System.err.println("Exit status=" + mtcheck_process.exitValue());
       
       String tempDir = null;
       String OS = System.getProperty("os.name").toLowerCase();
       
       if (OS.indexOf("win") >= 0){
           tempDir = "C:/Temp/mtcheck";
       } else{
           tempDir = "/tmp/mtcheck";
       }
       
       //get the name of the  generated XML from the CLI 
       //and parse it to generate the results table
       String path2ResultsXML = tempDir + "/" + resultsXML;
       
       //check if this file exists
       
       
       new ParseResultsXML().parse(path2ResultsXML);
       //checkDetails = new ParseResultsXML().getResultsXMLData();
       checkDetails = new ParseResultsXML().parse(path2ResultsXML);
       checkDetailsAll.addAll(checkDetails);       
    //return checkDetailsAll;
       return checkDetails;
}

    public static List<CheckDetail> getList(){
        return checkDetailsAll;
    }
    
    public static void cleanList(){
        checkDetailsAll.removeAll(checkDetailsAll);
    }
}

Open in new window

0
Big Business Goals? Which KPIs Will Help You

The most successful MSPs rely on metrics – known as key performance indicators (KPIs) – for making informed decisions that help their businesses thrive, rather than just survive. This eBook provides an overview of the most important KPIs used by top MSPs.

mccarlIT Business Systems Analyst / Software DeveloperCommented:
As I suspected, the fact that "mtcheck_process" is declared as static in this class means that "CheckRunner.mtcheck_process.destroy()" will only ever kill the last process that you execute. Because it is static, there can only ever be one instance of this in your whole program, and so if you start, for example, 5 processes, only the last process will have it's "Process" object stored in that value.

To fix will probably require a lot of code change, the general idea being....

 - Remove the "static" keyword from your CheckRunner.java for mtcheck_process (and you should probably look at doing that for "checkDetails" too, and while we are at it, you will likely have thread synchronization problems with "checkDetailsAll" the way you have done it)

 - In the code that creates all your "CheckRunner" objects (one for each task) you need to keep a reference to each of those objects somehow. When you want to kill all the processes, you iterate over that collection of "checkRunners" and then for each of them you can access your "mtcheck_process" instance variable to destroy it, or better still... follow some best practises and make mtcheck_process "private" and then provide a method in CheckRunner that actually does the "destroy"ing.

 - Call the above code (the bit that iterates of the list of checkRunners) in response to the user pressing the "stop" button, making sure you correctly handle any threading issues, etc.
0
TolgarAuthor Commented:
@mccarl: Would you be able to help me with the code, if I send you the whole code that you referred?

Thanks,
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Post your latest RunPerl.java and ToolbarListener.java and I will see what I can do! (Also, if you can note the line number in ToolbarListener.java that handles you "stop" action that might be useful)
0
TolgarAuthor Commented:
Thanks a lot mccarl!

RunPerl.java
public class RunPerl {
    
    
    static List<CheckDetail> checkDetails = null;
    final static List<CheckDetail> checkDetailsAll = new ArrayList<CheckDetail>();    
    static FileTree fileTree = new FileTree();
    
    private static Shell shell;
    private static Table table;
    private static String[] titles;
    private static Display display;
    private static Composite compTB3_table_newThread;
    //static Text txt;
    
    public static String[] getFileList(){
        String[] Filelist = null;
        
        return Filelist;
    }
    

        public static List<CheckDetail> runMwcheck(String content, Map<Integer, String> checkNameMap, Composite compTB3_table) throws IOException {
            Set<String> results = null;
            
            //String content = Gui.getFileList();          
            setcompTB3_table_newThread(compTB3_table);
            //separate the text by new line characters
            //and assign them to an array
            String fileData[] = content.split("(" + System.getProperty("line.separator") + ")+");
            
            
            //get the list of checks from the checks list in TAB2
            //Map<Integer, TreeItem> checkListMap = new HashMap<Integer, TreeItem>();
            //Map<Integer, String> checkNameMap= new HashMap<Integer, String>();
            //checkNameMap = CheckListTree.getInstance().getCheckedStandards(checkListMap, checkNameMap);
               
            String tempDir = null;
            StringBuilder checkList = new StringBuilder();
            Iterator<Map.Entry<Integer, String>> it_checkNameMap = checkNameMap.entrySet().iterator();
            // loop through the hashmap and create the checks list
            while (it_checkNameMap.hasNext()) {
                Map.Entry<Integer, String> pairs_checkNameMap = it_checkNameMap.next();
                checkList.append(" -guiCheck ").append(pairs_checkNameMap.getValue());
            }
            
            
             //loop through each line (request) in the text box
            
            String perlCmd;
            String mtcheckCmd;
            String setMtcheckPathCmd;
            String sandboxLocation = null;
            String batchFileCmd = null;
            //FutureTask<CheckRunner> task = new FutureTask(myRunner);
            //ExecutorService checkExecutor = Executors.newFixedThreadPool(5);
           ExecutorService checkExecutor = Executors.newSingleThreadExecutor();
            HashMap<String, Future> futures = new HashMap<String,Future>(fileData.length);
            //int j = 0;
            for (int j = 0; j < fileData.length; j++){
                //while (ToolBarListener.thread != null){
                    String fileInfoLine = fileData[j];
                    String OS = System.getProperty("os.name").toLowerCase();
                    //String lineBreak = System.getProperty("line.separator");
                    //fileInfoLine = fileInfoLine.replaceAll(lineBreak, " ");
                    fileInfoLine = fileInfoLine.replaceAll("\\r|\\n", "");
                    Pattern sandboxLocPattern = Pattern.compile("(?<=(-f|-d|-d -r|-c)).+?(?=(?:product))");
                    Matcher matchSandboxLoc = sandboxLocPattern.matcher(fileInfoLine);
                    if (matchSandboxLoc.find()){
                        sandboxLocation = matchSandboxLoc.group();
                        fileInfoLine = fileInfoLine.replace(sandboxLocation," ");
                        sandboxLocation = sandboxLocation.replaceAll("-f|-d|-d -r|-c", "");
                    } else{
                        
                    }
                    
                    if (OS.indexOf("win") >= 0){
                        tempDir = "C:/Temp/mtcheck";
                        batchFileCmd = "cmd.exe /C \\\\some\\path\\a\\batch\\file\\mtcheckGui.bat" +" " + sandboxLocation + " " + fileInfoLine + " " + checkList ;
                    }
                    else{
                         //not implemented yet for unix
                    }
                    perlCmd = batchFileCmd;
                    CheckRunner myRunner = new CheckRunner();
                    myRunner.setCommand(perlCmd);
                    futures.put(fileInfoLine, checkExecutor.submit(myRunner));       
                   //}
                }
            
            
            boolean exitLoop = false;
            boolean newRun = true;
            boolean evenRow = true;
            
            //Disable the runCheck button in the 2nd tab 
            //to prevent the user from using it
            //while the other processes are running.
             //Gui.item23.setEnabled(false);
             String fileName = null;
            while(true && exitLoop == false) {
                
            HashMap<String, Future> tempFutures = futures;   
            ArrayList<String> keyList = new ArrayList<String>();
            
            for (Entry<String, Future> entry  : tempFutures.entrySet()) {
                Future<List<CheckDetail>> f = entry.getValue();
                    try {
                        List<CheckDetail> checkDetails = f.get(1, TimeUnit.MILLISECONDS);
                        
                        if (checkDetails != null) {
                            keyList.add(entry.getKey());
                            checkDetailsAll.addAll(checkDetails); 
                            evenRow = Gui.populateResultsTable(checkDetails,shell,table,titles, newRun, evenRow);
                            newRun = false;
//                            if (evenRow){
//                                evenRow = false;
//                            } else {
//                                evenRow = true;                                
//                            }
                            
                        }
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (TimeoutException e) {
                       ;
                    }
                    //This is to set the initial set of data in the table to save the relevant information to a xml file.
                    CSFilteringCheckBoxes.setTableDataInitialData();
            }    

            if (!futures.isEmpty()){             
                for (String key : keyList) {
                    futures.remove(key);
                }                        
            }
            
            if (futures.isEmpty())
               exitLoop = true;
            }

            checkExecutor.shutdown();
            //Gui.item23.setEnabled(true);
                        
            return checkDetailsAll;
        }
        
        public void setTable(Table table, String[] titles) {
            RunPerl.table = table;
            RunPerl.titles = titles;
        }  
        
        
        public void setShell(Shell shell, Display display) {
            RunPerl.shell = shell; 
            RunPerl.display = display;
        }
        
        public static void setcompTB3_table_newThread(Composite combTB3){
            compTB3_table_newThread = combTB3;
        }
        
        public Composite getcompTB3_table_newThread(){
            return compTB3_table_newThread;
        }
        
        
        public static void saveResults(String file) throws ParserConfigurationException, IOException, ClassNotFoundException{
            DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
            //get current date time with Date()
            Date date = new Date();

            
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.newDocument();
         
            Element rootElement = doc.createElement("Results");
            doc.appendChild(rootElement);
            
            Element dateElement = doc.createElement("Date");
            rootElement.appendChild(dateElement);
            dateElement.setTextContent(dateFormat.format(date));
            //List<CheckDetail> checkDetailsTable = Gui.getTableData();
            List<CheckDetail> checkDetailsTableAll = CSFilteringCheckBoxes.getTableData();
            
            for (CheckDetail checkDetail : checkDetailsTableAll) {
                Element detailElement = doc.createElement("Detail");
                rootElement.appendChild(detailElement);

                Element nameElement = doc.createElement("name");
                detailElement.appendChild(nameElement);
                nameElement.setTextContent(checkDetail.getFileName());

                Element checkElement = doc.createElement("check");
                detailElement.appendChild(checkElement);
                checkElement.setTextContent(checkDetail.getName());

                Element statusElement = doc.createElement("status");
                detailElement.appendChild(statusElement);
                statusElement.setTextContent(checkDetail.getStatus());

                Element existingLineNumbersElement= doc.createElement("existingLineNumbers");
                detailElement.appendChild(existingLineNumbersElement);
                existingLineNumbersElement.setTextContent(checkDetail.getExistingLineNumbers());

                Element newLineNumbersElement= doc.createElement("newLineNumbers");
                detailElement.appendChild(newLineNumbersElement);
                newLineNumbersElement.setTextContent(checkDetail.getNewLineNumbers());

            }


            Transformer transformer = null;
            try {
                transformer = TransformerFactory.newInstance().newTransformer();
            } catch (TransformerConfigurationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (TransformerFactoryConfigurationError e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
    
   
            // This is to serialize to a File
            FileWriter fileWriter = null;
            try {
                fileWriter = new FileWriter(file);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                transformer.transform(new DOMSource(doc), new StreamResult(fileWriter));
            } catch (TransformerException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            try {
                fileWriter.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
}

Open in new window


And this is where the stop action should be in the ToolbarListener.java:

        } else if (toolItem == Gui.item33){
            if (thread != null){
                if(thread.getState()!=Thread.State.TERMINATED){
                    MessageBox box = new MessageBox(shell, SWT.ICON_QUESTION | SWT.YES | SWT.NO);
                    box.setMessage("Are you sure to stop the running the process?");
                    box.setText("Confirmation");
                    if (box.open() != SWT.YES)
                      return;           
                    thread = null;
                }
            } 

Open in new window

0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Ok so modify CheckRunner.java as I mentioned in the previous post... something along the lines of...
public class CheckRunner {
...
private Process mtcheck_process;

... The  rest of CheckRunner code, and then at the bottom of the class add this method ...
public void stop() {
    if (mtcheck_process != null) {
        mtcheck_process.destroy();
    }
}

Open in new window


Now in RunPerl.java does something along the lines of...
public class RunPerl {
...
private static List<CheckRunner> checkRunners = new ArrayList<CheckRunners>();

... 

CheckRunner myRunner = new CheckRunner();
checkRunners.add(myRunner);                                          //  <---- Add this line to your existing code
myRunner.setCommand(perlCmd);
futures.put(fileInfoLine, checkExecutor.submit(myRunner));       

.. and at the bottom of your class add this method ...
public static void stopAllRunners() {
    for (CheckRunner runner : checkRunners) {
        if (runner != null) {
            runner.stop();
        }
    }
}

Open in new window


Now finally, in your ToolbarListener.java once you get confirmation from the user, you can do this...
RunPerl.stopAllRunners();

Open in new window



Whether there are other actions that you need to take in addition to just "destroy"ing the Process, in order to fully stop the whole task that is taking place, I will leave up to you to work out. But these actions can probably be located within these stop() or stopAllRunners() methods too. Note that this is not really considering any threading issues that may arise, because with the way the code is it is hard to determine what sort of effects there may be.
0
TolgarAuthor Commented:
It actually did not stop the process. I can see that it is outputting some stuff on the eclipse console. and it keeps putting data on the table in the GUI.

What else should I do to really stop the process?
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
This is definitely getting into the territory of "hard to debug remotely" since we can't actually run your code ourselves to see what is happening and work out a solution for you.

It actually did not stop the process. I can see that it is outputting some stuff on the eclipse console. and it keeps putting data on the table in the GUI.
The fact that stuff is happening on the Eclipse console and on the table in the GUI, is NOT an indication that the process did/didn't stop. The process is just the Perl stuff, and killing/stopping that will not affect all the other code that you in Java that is reading the output of those Perl processes and populating the table, etc. If you want to be able to stop all of that, then that is a different question!
0
TolgarAuthor Commented:
I understand. It's really hard to debug remotely.

Yes, I would like to stop all of the things you mentioned. Especially, populating the results on the  table.

What do you think I should do?
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Maybe you could use your "exitLoop" flag variable (in RunPerl) to stop that loop early too. So something along the lines of... make "exitLoop" a static variable of the class (rather than the local variable that it currently is) but keep the "exitLoop = false;" line where it currently is. In the new stopAllRunners() method, set that exitLoop = true before you start calling all the runner.stop() methods. And then also you would probably want to put a check of the exitLoop variable inside the "for (Entry<String, Future> entry  : tempFutures.entrySet())" loop too. Even though the outer loop will exit when exitLoop becomes true, if you put a check inside that inner loop aswell, then you can exit the loop even earlier, something like "if (exitLoop) break;" placed just inside the tempFutures.entrySet() loop should be enough.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.