RFR [15] 8236825: Reading output from ... using ProcessBuilder/Process might hang
Paul Sandoz
paul.sandoz at oracle.com
Wed Jan 22 20:31:32 UTC 2020
My sense is it is fixing a marginal case for the less dominant platform where this is less likely arise, whereas for the dominant platform there is still an issue.
Waiting for a non-blocking native read is a reasonable approach (IIUC that is required for the desired proper fix). It would be useful to assess any time-frame of such support to plan ahead?
—
ProcessImpl
—
665 void processExited() {
666 synchronized (closeLock) {
667 try {
668 InputStream in = this.in;
669 // this stream is closed if and only if: in == null
670 if (in != null) {
671 boolean noCompete = false;
672 try {
673 // Briefly, wait for competing read to complete
674 noCompete = readLock.tryAcquire(500L, TimeUnit.MILLISECONDS);
675 if (noCompete) {
676 // no competing read, buffer any pending input
677 this.in = drainInputStream(in);
678 }
679 } catch (InterruptedException ie) {
680 // Ignore interrupt and release and close always
681 } finally {
682 readAborted = !noCompete;
683 in.close(); // close the original underlying input stream
684 if (noCompete)
685 readLock.release();
686 }
687 }
688 } catch (IOException ignored) {}
689 }
690 }
Do you need to move the code at lines 684-685 to occur before line 683? since in.close() could throw.
Paul.
> On Jan 21, 2020, at 12:36 PM, Roger Riggs <Roger.Riggs at oracle.com> wrote:
>
> Please review a potential way to address two issues of java.lang.Process deadlocks during process exit. [1] [2]
> (Linxu OS process expertise appreciated).
>
> The deadlock is between some thread reading process output from a process that has exited
> and the processExited thread that is attempting to buffer any remaining output so
> the file descriptor for the pipe can be closed. The methods involved are synchronized
> on a ProcessPipeInputStream instance.
>
> The hard case arises infrequently since the pipe streams are closed by the OS
> normally (or within a few seconds) and the readXXX completes.
> However, the case causing trouble is when the subprocess has spawned
> another process and both processes are using the same file descriptor/stream for output.
> Though the process that exits doesn't have the fd open anymore the extra subprocess does.
> And if that subprocess does not exit, then the read and deadlock does not get resolved.
>
> The approach proposed is to use a semaphore to guard the readXXX and
> providing some non-blocking logic in processExited to forcibly close
> the pipe if it detects that there is a conflicting read in progress.
> (And remove the synchronized on processExited).
>
> This solution works ok on MacOSX, where one of the issues occurred frequently.
> Closing the pipe unblocks the reading thread.
>
> On Linux, it appears that the blocking read (in native code) does not unblock
> unless a signal occurs; so the solution does not fix the problem adqurated/completely.
>
> Having a non-blocking native read would be the next step of complexity.
> The problem has been around for a while so it may be an option to wait
> for additional work on non-blocking pipe reads, the direction that Loom is moving.
>
> Suggestions welcome,
>
> Thanks, Roger
>
> Webrev: http://cr.openjdk.java.net/~rriggs/webrev-hdiutil-8236825/
>
> Issues:
> [1] https://bugs.openjdk.java.net/browse/JDK-8236825
> [2] https://bugs.openjdk.java.net/browse/JDK-8169565
More information about the core-libs-dev
mailing list