8 Replies Latest reply: May 5, 2011 11:39 AM by 858085 RSS

    Is there a better way to stop a Method than Thread.stop()?

    858085
      First my basic problem. In one of my programs I am using constraint solver. I call the constraint solver with a set of constraints and it returns a Map with a satisfying assignment. In most cases this works in acceptable time ( less than 1 second). But in some cases it may take hours. Currently I am running the function in a Thread and using Thread.stop(). This look like that:
           public Map<String, Object> getConcreteModel(
                     Collection<Constraint> constraints) {
                WorkingThread t=new WorkingThread(constraints);
                t.setName("WorkingThread");
                t.start();
                try {
                     t.join(Configuration.MAX_TIME);
                } catch (InterruptedException e) {
                }
                if(t.isAlive()){
                     t.stop();
                }
                return t.getSolution();
           }
      where t.getSolution(); returns null if the Thread was interrupted.

      Unfortunately this sometimes crashes the JVM with:
      #
      # A fatal error has been detected by the Java Runtime Environment:
      #
      #  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000006dbeb527, pid=5788, tid=4188
      #
      # JRE version: 6.0_18-b07
      # Java VM: Java HotSpot(TM) 64-Bit Server VM (16.0-b13 mixed mode windows-amd64 )
      # Problematic frame:
      # V  [jvm.dll+0x3fb527]
      #
      # An error report file with more information is saved as:
      # F:\Eigene Dateien\Masterarbeit\workspace\JPF-Listener-Test\hs_err_pid5788.log
      #
      # If you would like to submit a bug report, please visit:
      #   http://java.sun.com/webapps/bugreport/crash.jsp
      #
      Does anyone knows a better way to do it?

      Thank you in advance.

      Note 1: the Constraint solver is a Third Party tool and changing it is unfeasible. (I have tried it already)
      Note 2: Using Thread.stop(Throwable t) only chances the error message.
        • 1. Re: Is there a better way to stop a Method than Thread.stop()?
          796440
          Have you looked at the docs or contacted the creator of this 3rd party class about how to stop it mid-calculation? That would be the most sensible approach. Because Java does not provide a sanctioned means to stop a thread at an arbitrary point in its execution, it's up to individual classes/methods to provide means to stop their own execution where appropriate, so this is really a question about that library, rather than about Java per se. If they don't provide a means to stop their work, then it would seem that tool does not satisfy your requirements.

          Barring that, you could try t.interrupt(), or, worst case, t.suspend() or t.destroy() may or may not yield better results than t.stop()

          Edited by: jverd on Apr 27, 2011 9:50 AM
          • 2. Re: Is there a better way to stop a Method than Thread.stop()?
            858085
            Other tools are worse. And stopping the library those not work.

            I have read about that it would be possible to put the computation into another process using java.lang.Runtime.exec(). does anyone know how this could look like.

            Note both parameter and return values are serializeable so maybe with Object(in/out)putstream and getInputStream/getOutputStream.

            And if using another process how to get the result as soon as is ready, but still be able to kill the process when its hits the timeout.
            • 3. Re: Is there a better way to stop a Method than Thread.stop()?
              796440
              user7641489 wrote:
              Other tools are worse. And stopping the library those not work.

              I have read about that it would be possible to put the computation into another process using java.lang.Runtime.exec(). does anyone know how this could look like.

              Note both parameter and return values are serializeable so maybe with Object(in/out)putstream and getInputStream/getOutputStream.

              And if using another process how to get the result as soon as is ready, but still be able to kill the process when its hits the timeout.
              Exec a java program that just does that calculation, prints out the result, and then exits.

              http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html

              From Runtime.exec, or its preferred replacement, ProcessBuilder, you can get a java.lang.Process, which has a destroy() method.

              As for "getting the result as soon as it's ready," if you mean getting intermediate results on the fly, you can only do that if the library already provides a way to do that. Otherwise, if you mean just getting it as soon as the external process completes, you'll have it as soon as that process writes it out.

              Edited by: jverd on Apr 27, 2011 11:19 AM
              • 4. Re: Is there a better way to stop a Method than Thread.stop()?
                858085
                With that I mean that as soon as the Child prozess have printed the result I read them. InputStream.read() blocks thread until data is present. This may be longer than the timeout. Some for Process.waitfor().

                Busywaiting I would like to prevent, same goes for first waiting to end the timeout before checking if I have a result.
                • 5. Re: Is there a better way to stop a Method than Thread.stop()?
                  796440
                  user7641489 wrote:
                  With that I mean that as soon as the Child prozess have printed the result I read them. InputStream.read() blocks thread until data is present. This may be longer than the timeout. Some for Process.waitfor().

                  Busywaiting I would like to prevent, same goes for first waiting to end the timeout before checking if I have a result.
                  I don't understand what problem you're having.

                  You start a separate thread to read the input stream. As soon as the process writes anything and flushes, it will be available on that stream.

                  Separately from that--in your current thread, I would imagine, but possibly in a different thread, depending on details of your design--you wait a certain amount of time and then call destroy() on the process. You can do that with Thread.sleep() or with a timer. When you do that, the stream will give and IOException--possibly EOFException, but I'm not 100% sure.

                  There's no busy waiting here.

                  You didn't answer my questions in my first response though: Did you try calling interrupt() on the thread that's running the calculations? Did you look through the docs or contact the vendor to see if there's a supported method for interrupting a calculation in progress.
                  • 6. Re: Is there a better way to stop a Method than Thread.stop()?
                    858085
                    interrupt() doesen`t work.

                    And thanks for the Tip with the one thread which reads and the other which those the destroy() that was basiclly what I have missed.

                    And thanks for all the other help as well.
                    • 7. Re: Is there a better way to stop a Method than Thread.stop()?
                      796440
                      You're quite welcome.
                      • 8. Re: Is there a better way to stop a Method than Thread.stop()?
                        858085
                        In case somebody have the same problem here my code which solves the problem. Note it requires to parameters and the result to be serializable.

                        The Class which starts to Process:
                        public class Solver{
                        
                             public Map<String, Object> getConcreteModel(
                                       Collection<Constraint> constraints) {
                                       try
                                       {
                                            Process p=Runtime.getRuntime().exec(...); //do not forget the classpath
                                  
                                            
                                            new TimeOut(Configuration.MAX_TIME, p).start();
                                            ObjectOutputStream out=new ObjectOutputStream(p.getOutputStream());
                                            new ErrReader(p.getErrorStream()).start();//not that std.err fills up the pipe
                                            out.writeObject(constraints);
                                            out.flush();
                                            
                                            
                                            ObjectInputStream in=new ObjectInputStream(p.getInputStream());
                                            return (Map<String, Object>) in.readObject();
                                       }
                                       catch(IOException e)
                                       {
                                            return null;
                                       } catch (ClassNotFoundException e) {
                                            //should not happen
                                            return null;
                                       }
                             }
                        
                        
                             // For running in a own process
                             static private class TimeOut extends Thread
                             {
                                  private int time;
                                  private Process p;
                                  public TimeOut(int time, Process p)
                                  {
                                       this.time=time;
                                       this.p=p;
                                  }
                                  @Override
                                  public void run() {
                                       synchronized (this) {
                                            try {
                                                 this.wait(time);
                                            } catch (InterruptedException e) {
                                            }
                                       }
                                       
                                       p.destroy();
                                  }
                                  
                                  
                             }
                             
                             static class ErrReader extends Thread
                             {
                                 InputStream is;
                                 
                                 ErrReader(InputStream is)
                                 {
                                     this.is = is;
                                     this.setDaemon(true);
                                 }
                                 
                                 public void run()
                                 {
                                     try
                                     {
                                         InputStreamReader isr = new InputStreamReader(is);
                                         BufferedReader br = new BufferedReader(isr);
                                         String line=null;
                                         while ( (line = br.readLine()) != null)
                                             System.err.println(line);    
                                         } catch (IOException ioe)
                                           {
                                             ioe.printStackTrace();  
                                           }
                                 }
                             }
                        }
                        And the class which executet the Program
                        public class SolverProcess {
                        
                             /**
                              * @param args ignored
                              */
                             public static void main(String[] args){
                                  try {
                                       ObjectInputStream in =new ObjectInputStream(System.in);
                                       SolverProcess p=new SolverProcess();
                                       p.constraints=(Collection<Constraint>) in.readObject();
                                       p.compute();
                                       ObjectOutputStream out=new ObjectOutputStream(System.out);
                                       out.writeObject(p.solution);
                                       out.flush();
                                       
                                  } catch (Exception e) {
                                       // TODO Auto-generated catch block
                                       e.printStackTrace();
                                  }
                                  //System.err.println("solved");
                                  System.exit(0);
                             }
                             private Map<String, Object> solution=null;
                             private Collection<Constraint> constraints;
                        
                               private void compute()
                              {
                               ...
                              }
                        }