user1733583
user1733583

Reputation:

making process wait

I am using the following code to run terminal commands through my command prompt

String[] command =
        {
      "zsh"
          };
                Process p = Runtime.getRuntime().exec(command);
                new Thread(new SyncPipe(p.getErrorStream(), b)).start();
                new Thread(new SyncPipe(p.getInputStream(), b)).start();
                PrintWriter stdin = new PrintWriter(p.getOutputStream());
                stdin.println("source ./taxenv/bin/activate");
                stdin.println("python runner.py");
                stdin.close();
                int returnCode = 0;
                try {
                    returnCode = p.waitFor();

                    String path2 = b + "/logs.txt"; // I am getting b value passed in from gc.jsp
                    if(new File(path2).exists())
                    {
                        BufferedReader reader = new BufferedReader(new FileReader(path2));

                            while ((line1 = reader.readLine()) != null) 
                                {
                                    content= content + line1 +"<br>";
                                }
                            reader.close();
                            request.setAttribute("logs", content);

                            RequestDispatcher rd = request.getRequestDispatcher("gc.jsp");
                            rd.forward(request, response);


                }
                }
                catch (InterruptedException e) {
                    e.printStackTrace();

                }
                    System.out.println("Return code = " + returnCode +b);
    }               
    class SyncPipe implements Runnable
    {

    public SyncPipe(InputStream istrm, String c) {
          istrm_ = istrm;
          b_ = c;
      }

    @SuppressWarnings("unused")
    public void run() {
          try
          {
              final byte[] buffer = new byte[1024];
            for(int length = 0; (length = istrm_.read(buffer)) != -1; )
              {
                   str = str + IOUtils.toString(istrm_, "UTF-8") + b_;
              }
            System.out.println(str);

            String location = b_ + "/" + "logs.txt";
            File file = new File(location);
            if(!file.exists())
            {
                file.createNewFile();
            }
            FileWriter fw = new FileWriter(file.getAbsoluteFile());
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(str);
            bw.close();


          }

          catch (Exception e)
          {
              e.printStackTrace();
          }
      }
      private final InputStream istrm_;
      private final String b_;

When I run this code I expect it to be re directed to gc.jsp, but it displays as follows

enter image description here

Now, When I refresh the above page I am getting output as expected, shown below.

enter image description here

Why is this happening and how do I solve this?

=============================EDIT==========================

I've added

bw.close() //Closing bufferedwriter
fw.close() //Closing file writer

still of no use.

Now, I've added

TimeUnit.SECONDS.sleep(5);

This works fine for small files, so basically the problem is that code from the line

String path2 = b + "/logs.txt";

must wait for the process p to complete.

How do I do this?

Upvotes: 0

Views: 326

Answers (1)

Absurd-Mind
Absurd-Mind

Reputation: 7994

Your problem is that you try reading the files before your SyncPipes finished writing to your files. You can solve this by waiting until all threads are finished (join())

Process p = Runtime.getRuntime().exec(command);
Thread threadError = new Thread(new SyncPipe(p.getErrorStream(), b));
Thread threadInput = new Thread(new SyncPipe(p.getInputStream(), b));

threadError.start();
threadInput.start();

/* writing to process */

// wait until your process finished
p.waitFor();

// wait for both threads until they finished writing to files
threadError.join();
threadInput.join();

// read your files

Description: Your SyncPipe thread will stop when the Input/ErrorStream is closed because the process p stopped. Then it will write everything to file and close the files appropriately. After that the Thread is stopped correctly.

The join method tells your main thread (the caller of join) to wait until the thread is stopped (the callee of join, e.g. threadError). waitFor is somewhat equivalent to join.

After that you can say for sure that all threads are stopped correctly (p, threadError and threadInput) and therefore all files are written to disk. Now you can read them.

Upvotes: 1

Related Questions