2015-12-28 2 views
1

Я получаю значение «0» при вызове функции exitValue() для объекта процесса Java в linux, но иногда дочерние потоки (ошибка) не завершены и застревают в соединении. Должно ли «0» значение exitValue() процесса гарантировать, что все подпроцессы успешно завершены?Java process exitValue bug

private class ReadStdoutThread extends Thread { 
     private Process m_prc; 
     private StringBuffer m_sb; 

     public ReadStdoutThread(Process prc, StringBuffer sb) { 
      m_prc = prc; 
      m_sb = sb; 
     } 

     public void run() { 
      BufferedReader stdout = 
       new BufferedReader(new InputStreamReader(m_prc.getInputStream())); 
      String line = null; 
      try { 
       while ((line = stdout.readLine()) != null) { 
        System.out.println("Stdout: " + line); 
        m_sb.append(line + "\n"); 
       } 
       stdout.close(); 
      } catch (IOException e) { 
       System.out.println(e.toString()); 
       return; 
      } 
     } 
    } 

    private class ReadStderrThread extends Thread { 
     private Process m_prc; 
     private StringBuffer m_sb; 

     public ReadStderrThread(Process prc, StringBuffer sb) { 
      m_prc = prc; 
      m_sb = sb; 
     } 

     public void run() { 
      BufferedReader stderr = 
       new BufferedReader(new InputStreamReader(m_prc.getErrorStream())); 
      String line = null; 
      try { 
       while ((line = stderr.readLine()) != null) { 
        System.out.println("Stderr: " + line); 
        m_sb.append(line + "\n"); 
       } 
       stderr.close(); 
      } catch (IOException e) { 
       System.out.println(e.toString()); 
       return; 
      } 
     } 
    } 

    public static String runCmd(String cmd, long timeoutMS) throws IOException, 
                    InterruptedException { 
     Process prc = Runtime.getRuntime().exec(cmd); 
     long startTimeMS = System.currentTimeMillis(); 
     boolean isRunning = true; 
     System.out.println("Command has started."); 
     StringBuffer sb = new StringBuffer(); 
     ReadStdoutThread ot = new HostCommand().new ReadStdoutThread(prc, sb); 
     ReadStderrThread et = new HostCommand().new ReadStderrThread(prc, sb); 
     ot.start(); 
     et.start(); 
     if (timeoutMS == 0) { 
      System.out.println("Thread will wait until command is completed."); 
      prc.waitFor(); 
     } else { 
      System.out.println("Command timeout (ms): " + timeoutMS); 
      synchronized (prc) { 
       int n = -1; 
       while (isRunning) { 
        prc.wait(1000); 
        try { 
         n = prc.exitValue(); 
         System.out.println("Command has completed with value: " + 
              n); 
         m_processExitValue = n; 
         isRunning = false; 
        } catch (IllegalThreadStateException e) { 
         // command is still running 
         isRunning = true; 
        } 
        if ((System.currentTimeMillis() - startTimeMS > 
         timeoutMS) && isRunning) { 
         System.out.println("Timeout has reached, and command is still running. Command will be interrupted."); 
         prc.destroy(); 
         m_processExitValue = n; 
         isRunning = false; 
        } 
       } 
      } 
     } 
     try { 
      ot.join(timeoutMS); 
     } 
     catch(InterruptedException e) { 
      throw e; 
     } 
     try { 
      et.join(timeoutMS); 
     } 
     catch(InterruptedException e) { 
      throw e; 
     } 
     return sb.toString(); 
    } 
+0

Если процесс успешно завершен возвращает 0, остальное бросает IllegalThreadStateException, если подпроцесс, представленный этот объект процесса еще не завершен. –

+0

Подпроцесс означает потоки в этом случае? Я получаю возвращаемое значение как «0» для exitValue, но потоки процесса не завершаются и иногда застревают (0.01%). –

+0

Нет Это не резьба. Его основной процесс, создающий экземпляр подкласса Process, поэтому является подпроцессом. –

ответ

0

Согласно документации, метод должен возвращать IllegalThreadStateException если подпроцесс еще не прекращено, в противном случае она возвращает 0, который указывает нормальное завершение.

Источник: https://docs.oracle.com/javase/7/docs/api/java/lang/Process.html

+0

Согласитесь, но можно ли это считать ошибкой в ​​java/linux, если процесс возвращает «0», но все еще поток не завершил его выполнение? –

0

Там нет никакой гарантии, что ReadStdoutThread и ReadStderrThread закончили выполнение. Синхронизация между API процесса waitFor и двумя отдельными потоками, которые вы породили, чтобы читать стандартные потоки ввода и ошибок из процесса. Вы должны использовать: ot.join();et.join(); после вызова ot.start();et.start(); .Basically, Join должна вызываться перед вызовом Process.waitFor()