On Fri, 4 Dec 2020 09:53:00 GMT, Daniel Fuchs <dfu...@openjdk.org> wrote:

>> `InputStream` from `BodyPublishers.ofInputStream()` is usually closed when 
>> the stream reaches EOF. However IOE handler returns without closing.
>> 
>> I confirmed this problem in `BodyPublishers.ofInputStream()`, but I think 
>> `BodyPublishers.ofFile()`has same problem because it also use 
>> `StreamIterator`as well as `ofInputStream()`.
>> 
>> 
>> # How to reproduce:
>> 
>> Following code (Test.java) attempts to post body from `TestInputStream` 
>> which throws IOE in `read()`. "close called" is shown on the console if 
>> `close()` is called.
>> 
>> import java.io.*;
>> import java.net.*;
>> import java.net.http.*;
>> 
>> public class Test{
>> 
>>   private static class TestInputStream extends InputStream{
>> 
>>     public TestInputStream(){
>>       super();
>>       System.out.println("test c'tor");
>>     }
>> 
>>     @Override
>>     public int read() throws IOException{
>>       System.out.println("read called");
>>       throw new IOException("test");
>>     }
>> 
>>     @Override
>>     public void close() throws IOException{
>>       System.out.println("close called");
>>       super.close();
>>     }
>> 
>>   }
>> 
>>   public static void main(String[] args) throws Exception{
>>     var http = HttpClient.newHttpClient();
>>     var request = HttpRequest.newBuilder()
>>                              .uri(URI.create("http://httpbin.org/post";))
>>                              
>> .POST(HttpRequest.BodyPublishers.ofInputStream(() -> new TestInputStream()))
>>                              .build();
>>     http.send(request, HttpResponse.BodyHandlers.discarding());
>>     System.out.println("Press any key to exit...");
>>     System.in.read();
>>   }
>> }
>
> src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java 
> line 422:
> 
>> 420:             } catch (IOException ex) {
>> 421:                 need2Read = false;
>> 422:                 haveNext = false;
> 
> This shouldn't be required - `need2Read`/`haveNext` will be set by 
> `hasNext()`; I'd prefer if we kept the logic there.

We can close the stream in `hasNext()`, but we need to move `close()` from 
`read()`.
`need2Read` and `haveNext` will be set to `false` if `read()` returns -1. 
However `read()` returns -1 when IOE or EOF happen. Is it ok? I concern to 
change location of `close()` - it means the change of side-effect.

> src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java 
> line 426:
> 
>> 424:                     is.close();
>> 425:                 } catch (IOException ex2) {}
>> 426:                 return -1;
> 
> } catch (IOException ex2) {}
>                 return -1;
> 
> I wonder if the first exception `ex` should actually be rethrown here instead 
> of returning `-1`. Have you tried to explore this possibility?

`read()` is not have IOE as checked exception, and also currently IOE is 
ignored.
So I ignored IOE at `close()` in this PR to minimize side-effect.

-------------

PR: https://git.openjdk.java.net/jdk/pull/1614

Reply via email to