8078891: java.io.SequenceInputStream.close is not atomic and not idempotent

Pavel Rappo pavel.rappo at oracle.com
Fri Jul 26 11:14:47 UTC 2019


> On 25 Jul 2019, at 21:01, Brian Burkhalter <brian.burkhalter at oracle.com> wrote:

<snip>

> This concern would be fixed by changing the proposed patch as
> 
> --- a/src/java.base/share/classes/java/io/SequenceInputStream.java
> +++ b/src/java.base/share/classes/java/io/SequenceInputStream.java
> @@ -91,13 +91,10 @@
>       * Continues reading in the next stream if an EOF is reached.
>       */
>      final void nextStream() throws IOException {
> -        try {
> -            if (in != null) {
> -                in.close();
> -            }
> -        } finally {
> -            peekNextStream();
> +        if (in != null) {
> +            in.close();
>          }
> +        peekNextStream();
>      }
>  
>      private void peekNextStream() {
> @@ -233,6 +230,7 @@
>                  } else {
>                      ioe.addSuppressed(e);
>                  }
> +                peekNextStream();
>              }
>          } while (in != null);
>          if (ioe != null) {
> 
> That is to say reverting the nextStream() change and adding peekNextStream() in the catch branch of close(). I actually had it this way in a version I did not post.
> 
> The scenario you suggest however would seem to be somewhat of a coding error by the caller. I would think that once a sequence stream were created the component streams should not be used.

When I filed this bug I was mainly concerned with the fact that `close` may end
up closing only some of the component streams. Both your original and amended
patches seem to fix this problem. However, I prefer the amended version. As it
both does the job and preserves the original behavior when consuming data from
the current component stream.

The scenario I mentioned in my previous email was about continuous attempts to
read from the SequenceInputStream, not about reading component streams
"out-of-band" (bypassing the aggregating SequenceInputStream). Sorry if I
didn't make myself clear.

This scenario doesn't seem to be a programming error, albeit a very strange use
case. I must admit I haven't seen any code in the wild doing so. Yet the spec
does not seem to prohibit this.

A nit on the accompanying test. Please consider this change:

diff -r 5a65ed97e38b test/jdk/java/io/SequenceInputStream/Close.java
--- a/test/jdk/java/io/SequenceInputStream/Close.java	Fri Jul 26 12:10:08 2019 +0100
+++ b/test/jdk/java/io/SequenceInputStream/Close.java	Fri Jul 26 12:12:29 2019 +0100
@@ -27,17 +27,15 @@
  */
 
 import java.io.ByteArrayInputStream;
-import java.io.InputStream;
 import java.io.IOException;
 import java.io.SequenceInputStream;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.List;
 
 public class Close {
 
-    public static void main(String[] argv) throws IOException {
+    public static void main(String[] argv) {
         byte[] buf = new byte[42];
 
         List<CloseableBAOS> list = List.of(new CloseableBAOS(buf),
@@ -74,12 +72,12 @@
 
     static class CloseableBAOS extends ByteArrayInputStream{
         private boolean closed;
-        private int numCloses = 0;
 
         CloseableBAOS(byte[] buf) {
             super(buf);
         }
 
+        @Override
         public void close() throws IOException {
             closed = true;
             throw new IOException();




More information about the core-libs-dev mailing list