java Process' inputStream stuck

后端 未结 1 676
时光取名叫无心
时光取名叫无心 2021-01-21 06:04

Here\'s my scenario:

  1. process A spawns child process B and spins threads to drain B\'s outputs.
  2. process B spawns daemon process C and drains its outputs, t
相关标签:
1条回答
  • 2021-01-21 06:57

    I just encountered the same problem. I think I have a workaround to the problem. In process A, I have the following code fragment after Process.waitFor(), where outT and errT are the threads to read process B's stdout and stderr, respectively:

    try {
      outT.join(1000);
      if (outT.isAlive()) {
        errmsg("stdout reader still alive, interrupting", null);
        outT.interrupt();
      }
    } catch (Exception e) {
      errmsg("Exception caught from out stream reader: "+e, e);
    }
    try {
      errT.join(1000);
      if (errT.isAlive()) {
        errmsg("stderr reader still alive, interrupting", null);
        errT.interrupt();
      }
    } catch (Exception e) {
      errmsg("Exception caught from err stream reader: "+e, e);
    }
    p.destroy();
    

    Not sure if p.destroy() is needed, but I have been trying all kinds of combinations to deal with the problem.

    Anyway, in the run() method of the outT/errT threads, I have the following, where the 'pipe' variable is a Writer instance I am capturing stdout/stderr of the sub-process to. The 'in' variable is the stdout, or stderr, stream obtained from Process:

    try {
      r = new BufferedReader(new InputStreamReader(in, enc));
      String line;
      while (true) {
        if (Thread.currentThread().isInterrupted()) {
          errmsg("Text stream reader interrupted", null);
          break;
        }
        if (r.ready()) {
          line = r.readLine();
          if (line == null) {
            break;
          }
          pipe.write(line);
          pipe.write(SystemUtil.EOL);
          if (autoFlush) {
            pipe.flush();
          }
        }
      }
      pipe.flush();
    
    } catch (Throwable t) {
      errmsg("Exception caught: "+t, t);
      try { pipe.flush(); } catch (Exception noop) {}
    
    } finally {
      IOUtil.closeQuietly(in);
      IOUtil.closeQuietly(r);
    }
    

    It seems that I never get an EOF indication from any sub-process, even after the sub-process terminates, hence, all the chicanery above to prevent stale threads and blocking.

    0 讨论(0)
提交回复
热议问题