This discussion is archived
8 Replies Latest reply: May 5, 2011 9:39 AM by 858085 RSS

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

858085 Newbie
Currently Being Moderated
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 Guru
    Currently Being Moderated
    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 Newbie
    Currently Being Moderated
    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 Guru
    Currently Being Moderated
    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 Newbie
    Currently Being Moderated
    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 Guru
    Currently Being Moderated
    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 Newbie
    Currently Being Moderated
    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 Guru
    Currently Being Moderated
    You're quite welcome.
  • 8. Re: Is there a better way to stop a Method than Thread.stop()?
    858085 Newbie
    Currently Being Moderated
    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()
          {
           ...
          }
    }

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points