JDK-8171426 : java/lang/ProcessBuilder/Basic.java failed with Stream closed
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 9,10
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris
  • CPU: x86_64
  • Submitted: 2016-12-19
  • Updated: 2019-06-05
  • Resolved: 2018-12-04
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 12
12 b23Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Description
----------System.out:(22/959)*----------
This appears to be a Unix system.
Testing ASCII environment values
Testing Latin1 environment values
Testing Unicode environment values
Testing directory .
Testing directory ..
Testing directory /
Testing directory /bin
cmdp
cmdp 0: /scratch/jenkins/workspace/9-dev/build/jdk/bin/java
cmdp 1: -XX:+DisplayVMOutputToStderr
cmdp 2: -classpath
cmdp 3: /scratch/jenkins/workspace/9-dev/testresults/solaris-x64/jdk_test.tier1/jtreg/JTwork/classes/2/java/lang/ProcessBuilder:/scratch/jenkins/workspace/9-dev/jdk/test/java/lang/ProcessBuilder:/scratch/jenkins/workspace/mach5data/install/java/re/jtreg/4.2/promoted/all/b04/bundles/jtreg_bin-4.2.zip/jtreg/lib/javatest.jar:/scratch/jenkins/workspace/mach5data/install/java/re/jtreg/4.2/promoted/all/b04/bundles/jtreg_bin-4.2.zip/jtreg/lib/jtreg.jar
cmdp 4: Basic$JavaChild
cmdp 5: System.getenv()
envp
envp 0: LC_ALL=C\u0000\u0000
envp 1: FO\u0000=B\u0000R
 waitFor process: delta: 291667

Passed = 9211, failed = 1

----------System.err:(18/1081)----------
java.io.IOException: Stream closed
	at java.base/java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:170)
	at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:214)
	at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:265)
	at Basic$13.run(Basic.java:2174)
java.lang.AssertionError: Some tests failed
	at Basic.main(Basic.java:2702)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:538)
	at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:110)
	at java.base/java.lang.Thread.run(Thread.java:844)

Comments
Resolved to modify the test to accept the current implementation behavior. Review thread: http://mail.openjdk.java.net/pipermail/core-libs-dev/2018-November/056889.html
27-11-2018

The behavior of BufferedInputStream is the root cause. The BufferedInputStream count and pos indicate there is data to be returned but the buffer is discarded before it can be returned. One fix is proposed above but would change the behavior to return the available data if in the middle of read and delay the return of -1 for EOF. The read(byte[], off, len), skip(n), and reset() methods would still throw IOE("stream closed") instead of signaling EOF with -1. However, the assertion in the test: // Check that reads which are pending when Process.destroy is // called, get EOF, not IOException("Stream closed"). Is an assertion against the ProcessImpl.ProcessPipeInputStream introduced by 6944584 and is not a requirement on BufferedInputStream. The specific behavior of the InputStreams returned from Process.getInput/ErrorStream are not specified. The behavior is implementation specific. Two solutions: 1) Maintain the current behavior of the implementation and revise the test to allow the throwing of IOE("stream closed") 2) Override read and skip methods in ProcessImpl.ProcessPipeInputStream to catch IOE("stream closed") and return -1(EOF) as expected by the test.
21-11-2018

Hypothesis on how this happens: java.io.IOException: Stream closed at java.base/java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:176) at java.base/java.io.BufferedInputStream.read1(BufferedInputStream.java:297) at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:351) at java.base/java.io.FilterInputStream.read(FilterInputStream.java:107) at Basic$12.run(Basic.java:2111) Note that buf can be cleared at any time; it is volatile and updated in close() (not synchronized) using compareAndSetReference. In BufferedInputStream.read1 suppose count and pos indicate there are still bytes in 'buf'. read1 is synchronized because it was called from read(b[],off, len) but that does it no good because of how the volatile buf is updated. So if close() is called at line 296; buf will be null and it will throw IOException. It would seem that read1 should hold on to the buffer address while it is checking (count - pos) A similar gap exists in read() at line 275.
07-11-2018

Hypothesis: The test is expecting eof(-1) instead of "stream closed" exception. On Solaris the DeferredCloseInputStream is wrapped by a BufferedInputStream. Destroying the process (may defer if a read is in progress) but closes the BufferedInputStream. BufferedInputStream.close (line 485) clears "buf" using Unsafe causing the "stream closed" exception when it is next referenced. BufferedInputStream returns -1 only when the underlying stream returns EOF (-1) but not when the stream itself is closed. Suppose the fill (line 271) succeeds (because the "Terminated" text appears in stdout). But before it can be returned DeferredCloseInputStream forcibly closes the BufferedInputStream causing the "stream closed" exception.
06-03-2018

The failure occurred in the 2nd of two test runs: * @run main/othervm/timeout=300 -Djdk.lang.Process.launchMechanism=fork Basic
19-12-2016