Re: [tomcat] branch master updated: Fix the HTTP/2 equivalent of swallowInput

2019-04-09 Thread Rémy Maucherat
On Tue, Apr 9, 2019 at 10:43 AM Mark Thomas  wrote:

> On 09/04/2019 08:50, Rémy Maucherat wrote:
>
> 
>
> > Thanks for the fix. I can indeed see that HttpParser.onHeadersComplete
> has:
> > output.headersEnd(streamId); // <- dispatch is done here
> >
> > if (headersEndStream) {
> > output.receivedEndOfStream(streamId);
> > headersEndStream = false;
> > }
> >
> > I guess it's possible to rely on syncing but normally thread dispatching
> > should not occur until after the state is properly set, it's simply
> safer.
>
> I did think about swapping the order of those statements. When I tested
> it I saw one test failure with trailer headers (I didn't investigate
> further) so I went for a different solution.
>

There is a failure indeed, but it's a logging issue only it seems (the
callback log the events in order, so it doesn't match the comparison string
anymore).


>
> It may be the swapping the order is safe but that would need more
> investigation. Also, triggering EOS before end of headers just seems
> wrong to me.
>

I agree it seems wrong. There's another occurrence of the behavior though,
in Http2Parser.readDataFrame, where it does:
if (endOfStream) {
output.receivedEndOfStream(streamId);
}
output.endRequestBodyFrame(streamId);

I will try to investigate, but only after the next build, it's clearly not
worth breaking something.

Rémy


Re: [tomcat] branch master updated: Fix the HTTP/2 equivalent of swallowInput

2019-04-09 Thread Mark Thomas
On 09/04/2019 08:50, Rémy Maucherat wrote:



> Thanks for the fix. I can indeed see that HttpParser.onHeadersComplete has:
> output.headersEnd(streamId); // <- dispatch is done here
> 
> if (headersEndStream) {
> output.receivedEndOfStream(streamId);
> headersEndStream = false;
> }
> 
> I guess it's possible to rely on syncing but normally thread dispatching
> should not occur until after the state is properly set, it's simply safer.

I did think about swapping the order of those statements. When I tested
it I saw one test failure with trailer headers (I didn't investigate
further) so I went for a different solution.

It may be the swapping the order is safe but that would need more
investigation. Also, triggering EOS before end of headers just seems
wrong to me.

Mark

-
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org



Re: [tomcat] branch master updated: Fix the HTTP/2 equivalent of swallowInput

2019-04-09 Thread Rémy Maucherat
On Mon, Apr 8, 2019 at 10:49 PM Mark Thomas  wrote:

> On 08/04/2019 20:38, Mark Thomas wrote:
>
> 
>
> > I'm not sure. Do you have the complete logs for those tests? I'd like to
> > look at everything sent from the client to the server for stream 3.
>
> Thanks for the logs (sent off-list). They didn't line up with my code
> which made me realise I was working with the 8.5.x branch rather than
> master. As soon as I switched to the right branch I was able to exploit
> the timing gap I thought I'd found.
>
> > I'd got as far as thinking that the server wasn't (always) marking
> > stream 3 as half-closed and my next steps are to try and figure out why.
>
> The short version is that the thread (A) parsing the incoming frames
> first signals end of headers. This starts the container thread (B) with
> a new StreamProcessor to process the request.
>
> Thread A then continues and signals end of stream.
>
> If Thread B processes the request, writes the response and gets as far
> as the new check I added before thread A signals end of stream, you see
> the reset.
>
> This only happens with NIO2.
>
> There should be a sync that prevents this. There is in the non-async case.
>
> Next steps are to figure out which sync is missing and where it needs to
> go.
>

Thanks for the fix. I can indeed see that HttpParser.onHeadersComplete has:
output.headersEnd(streamId); // <- dispatch is done here

if (headersEndStream) {
output.receivedEndOfStream(streamId);
headersEndStream = false;
}

I guess it's possible to rely on syncing but normally thread dispatching
should not occur until after the state is properly set, it's simply safer.

Rémy


>
> Mark
>
> -
> To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
> For additional commands, e-mail: dev-h...@tomcat.apache.org
>
>


Re: [tomcat] branch master updated: Fix the HTTP/2 equivalent of swallowInput

2019-04-08 Thread Mark Thomas
On 08/04/2019 20:38, Mark Thomas wrote:



> I'm not sure. Do you have the complete logs for those tests? I'd like to
> look at everything sent from the client to the server for stream 3.

Thanks for the logs (sent off-list). They didn't line up with my code
which made me realise I was working with the 8.5.x branch rather than
master. As soon as I switched to the right branch I was able to exploit
the timing gap I thought I'd found.

> I'd got as far as thinking that the server wasn't (always) marking
> stream 3 as half-closed and my next steps are to try and figure out why.

The short version is that the thread (A) parsing the incoming frames
first signals end of headers. This starts the container thread (B) with
a new StreamProcessor to process the request.

Thread A then continues and signals end of stream.

If Thread B processes the request, writes the response and gets as far
as the new check I added before thread A signals end of stream, you see
the reset.

This only happens with NIO2.

There should be a sync that prevents this. There is in the non-async case.

Next steps are to figure out which sync is missing and where it needs to go.

Mark

-
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org



Re: [tomcat] branch master updated: Fix the HTTP/2 equivalent of swallowInput

2019-04-08 Thread Mark Thomas
On 08/04/2019 14:16, Rémy Maucherat wrote:
> On Mon, Apr 8, 2019 at 11:05 AM Mark Thomas  wrote:
>> On 08/04/2019 09:57, Rémy Maucherat wrote:
>>> On Sun, Apr 7, 2019 at 10:42 PM  wrote:



 commit 6d3c117384c11f1bfd9393fb1484cd5a708a8245
 Author: Mark Thomas 
 AuthorDate: Sun Apr 7 21:39:15 2019 +0100

 Fix the HTTP/2 equivalent of swallowInput

 When Tomcat writes a final response without reading all of an HTTP/2
 request, reset the stream to inform the client that the remaining
 request body is not required.

>>>
>>> After this change, I do get this CI failure "reliably":
>>>
>> https://ci.apache.org/projects/tomcat/tomcat9/logs/4183/TEST-org.apache.coyote.http2.TestHttp2Section_6_8.NIO2.txt
>>>
>>> Unsure if this is relatively normal or a bug.
>>
>> I saw that failure but couldn't reproduce it locally. I'll take another
>> look.
>>
> 
> It seems ok to ignore it for now, it doesn't really look related although I
> didn't get it before.
> 
> With logging, it goes like this at the end of the test:
> FAIL:
> 08-Apr-2019 10:50:18.982 FINE [main]
> org.apache.coyote.http2.HpackEncoder.encode Encoding header [:method] with
> value [GET]
> 08-Apr-2019 10:50:18.982 FINE [main]
> org.apache.coyote.http2.HpackEncoder.encode Encoding header [:scheme] with
> value [http]
> 08-Apr-2019 10:50:18.982 FINE [main]
> org.apache.coyote.http2.HpackEncoder.encode Encoding header [:path] with
> value [/simple]
> 08-Apr-2019 10:50:18.982 FINE [main]
> org.apache.coyote.http2.HpackEncoder.encode Encoding header [:authority]
> with value [localhost:41523]
> 08-Apr-2019 10:50:18.982 FINE [main]
> org.apache.coyote.http2.Http2Parser.validateFrame Connection [-1], Stream
> [3], Frame type [HEADERS], Flags [4], Payload size [37]
> 08-Apr-2019 10:50:18.982 FINE [http-nio2-127.0.0.1-auto-1-exec-4]
> org.apache.coyote.http2.Http2Parser.validateFrame Connection [0], Stream
> [5], Frame type [HEADERS], Flags [5], Payload size [4]
> 08-Apr-2019 10:50:18.982 FINE [main]
> org.apache.coyote.http2.Http2Parser.readHeaderPayload Connection [-1],
> Stream [3], Processing headers payload of size [37]
> 08-Apr-2019 10:50:18.983 FINE [main]
> org.apache.coyote.http2.Http2Parser.swallow Connection [-1], Stream [3],
> Swallowed [0] bytes
> 08-Apr-2019 10:50:18.983 FINE [main]
> org.apache.coyote.http2.Http2Parser.validateFrame Connection [-1], Stream
> [3], Frame type [DATA], Flags [1], Payload size [8192]
> 08-Apr-2019 10:50:18.983 FINE [main]
> org.apache.coyote.http2.Http2Parser.readDataFrame Connection [-1], Stream
> [3], Data length, [8192], Padding length [none]
> 08-Apr-2019 10:50:18.983 FINE [main]
> org.apache.coyote.http2.Http2Parser.swallow Connection [-1], Stream [3],
> Swallowed [8192] bytes
> 08-Apr-2019 10:50:18.983 FINE [main]
> org.apache.coyote.http2.Http2Parser.validateFrame Connection [-1], Stream
> [3], Frame type [RST], Flags [0], Payload size [4]
> 08-Apr-2019 10:50:18.984 INFO [main]
> org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler
> ["http-nio2-127.0.0.1-auto-1-41523"]
> 08-Apr-2019 10:50:18.984 INFO [main]
> org.apache.catalina.core.StandardService.stopInternal Stopping service
> [Tomcat]
> 08-Apr-2019 10:50:18.996 INFO [main]
> org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler
> ["http-nio2-127.0.0.1-auto-1-41523"]
> 
> vs PASS:
> 08-Apr-2019 15:06:16.315 FINE [main]
> org.apache.coyote.http2.HpackEncoder.encode Encoding header [:method] with
> value [GET]
> 08-Apr-2019 15:06:16.316 FINE [main]
> org.apache.coyote.http2.HpackEncoder.encode Encoding header [:scheme] with
> value [http]
> 08-Apr-2019 15:06:16.317 FINE [main]
> org.apache.coyote.http2.HpackEncoder.encode Encoding header [:path] with
> value [/simple]
> 08-Apr-2019 15:06:16.317 FINE [main]
> org.apache.coyote.http2.HpackEncoder.encode Encoding header [:authority]
> with value [localhost:34997]
> 08-Apr-2019 15:06:16.318 FINE [main]
> org.apache.coyote.http2.Http2Parser.validateFrame Connection [-1], Stream
> [3], Frame type [HEADERS], Flags [4], Payload size [37]
> 08-Apr-2019 15:06:16.318 FINE [http-nio2-127.0.0.1-auto-1-exec-6]
> org.apache.coyote.http2.Http2Parser.validateFrame Connection [0], Stream
> [5], Frame type [HEADERS], Flags [5], Payload size [4]
> 08-Apr-2019 15:06:16.318 FINE [main]
> org.apache.coyote.http2.Http2Parser.readHeaderPayload Connection [-1],
> Stream [3], Processing headers payload of size [37]
> 08-Apr-2019 15:06:16.319 FINE [main]
> org.apache.coyote.http2.Http2Parser.swallow Connection [-1], Stream [3],
> Swallowed [0] bytes
> 08-Apr-2019 15:06:16.320 FINE [main]
> org.apache.coyote.http2.Http2Parser.validateFrame Connection [-1], Stream
> [3], Frame type [DATA], Flags [1], Payload size [8192]
> 08-Apr-2019 15:06:16.320 FINE [main]
> org.apache.coyote.http2.Http2Parser.readDataFrame Connection [-1], Stream
> [3], Data length, [8192], Padding length [none]
> 08-Apr-2019 15:06:16.321 FINE [main]
> 

Re: [tomcat] branch master updated: Fix the HTTP/2 equivalent of swallowInput

2019-04-08 Thread Rémy Maucherat
On Mon, Apr 8, 2019 at 11:05 AM Mark Thomas  wrote:

> On 08/04/2019 09:57, Rémy Maucherat wrote:
> > On Sun, Apr 7, 2019 at 10:42 PM  wrote:
> >
> >> This is an automated email from the ASF dual-hosted git repository.
> >>
> >> markt pushed a commit to branch master
> >> in repository https://gitbox.apache.org/repos/asf/tomcat.git
> >>
> >>
> >> The following commit(s) were added to refs/heads/master by this push:
> >>  new 6d3c117  Fix the HTTP/2 equivalent of swallowInput
> >> 6d3c117 is described below
> >>
> >> commit 6d3c117384c11f1bfd9393fb1484cd5a708a8245
> >> Author: Mark Thomas 
> >> AuthorDate: Sun Apr 7 21:39:15 2019 +0100
> >>
> >> Fix the HTTP/2 equivalent of swallowInput
> >>
> >> When Tomcat writes a final response without reading all of an HTTP/2
> >> request, reset the stream to inform the client that the remaining
> >> request body is not required.
> >>
> >
> > After this change, I do get this CI failure "reliably":
> >
> https://ci.apache.org/projects/tomcat/tomcat9/logs/4183/TEST-org.apache.coyote.http2.TestHttp2Section_6_8.NIO2.txt
> >
> > Unsure if this is relatively normal or a bug.
>
> I saw that failure but couldn't reproduce it locally. I'll take another
> look.
>

It seems ok to ignore it for now, it doesn't really look related although I
didn't get it before.

With logging, it goes like this at the end of the test:
FAIL:
08-Apr-2019 10:50:18.982 FINE [main]
org.apache.coyote.http2.HpackEncoder.encode Encoding header [:method] with
value [GET]
08-Apr-2019 10:50:18.982 FINE [main]
org.apache.coyote.http2.HpackEncoder.encode Encoding header [:scheme] with
value [http]
08-Apr-2019 10:50:18.982 FINE [main]
org.apache.coyote.http2.HpackEncoder.encode Encoding header [:path] with
value [/simple]
08-Apr-2019 10:50:18.982 FINE [main]
org.apache.coyote.http2.HpackEncoder.encode Encoding header [:authority]
with value [localhost:41523]
08-Apr-2019 10:50:18.982 FINE [main]
org.apache.coyote.http2.Http2Parser.validateFrame Connection [-1], Stream
[3], Frame type [HEADERS], Flags [4], Payload size [37]
08-Apr-2019 10:50:18.982 FINE [http-nio2-127.0.0.1-auto-1-exec-4]
org.apache.coyote.http2.Http2Parser.validateFrame Connection [0], Stream
[5], Frame type [HEADERS], Flags [5], Payload size [4]
08-Apr-2019 10:50:18.982 FINE [main]
org.apache.coyote.http2.Http2Parser.readHeaderPayload Connection [-1],
Stream [3], Processing headers payload of size [37]
08-Apr-2019 10:50:18.983 FINE [main]
org.apache.coyote.http2.Http2Parser.swallow Connection [-1], Stream [3],
Swallowed [0] bytes
08-Apr-2019 10:50:18.983 FINE [main]
org.apache.coyote.http2.Http2Parser.validateFrame Connection [-1], Stream
[3], Frame type [DATA], Flags [1], Payload size [8192]
08-Apr-2019 10:50:18.983 FINE [main]
org.apache.coyote.http2.Http2Parser.readDataFrame Connection [-1], Stream
[3], Data length, [8192], Padding length [none]
08-Apr-2019 10:50:18.983 FINE [main]
org.apache.coyote.http2.Http2Parser.swallow Connection [-1], Stream [3],
Swallowed [8192] bytes
 08-Apr-2019 10:50:18.983 FINE [main]
org.apache.coyote.http2.Http2Parser.validateFrame Connection [-1], Stream
[3], Frame type [RST], Flags [0], Payload size [4]
08-Apr-2019 10:50:18.984 INFO [main]
org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler
["http-nio2-127.0.0.1-auto-1-41523"]
08-Apr-2019 10:50:18.984 INFO [main]
org.apache.catalina.core.StandardService.stopInternal Stopping service
[Tomcat]
08-Apr-2019 10:50:18.996 INFO [main]
org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler
["http-nio2-127.0.0.1-auto-1-41523"]

vs PASS:
08-Apr-2019 15:06:16.315 FINE [main]
org.apache.coyote.http2.HpackEncoder.encode Encoding header [:method] with
value [GET]
08-Apr-2019 15:06:16.316 FINE [main]
org.apache.coyote.http2.HpackEncoder.encode Encoding header [:scheme] with
value [http]
08-Apr-2019 15:06:16.317 FINE [main]
org.apache.coyote.http2.HpackEncoder.encode Encoding header [:path] with
value [/simple]
08-Apr-2019 15:06:16.317 FINE [main]
org.apache.coyote.http2.HpackEncoder.encode Encoding header [:authority]
with value [localhost:34997]
08-Apr-2019 15:06:16.318 FINE [main]
org.apache.coyote.http2.Http2Parser.validateFrame Connection [-1], Stream
[3], Frame type [HEADERS], Flags [4], Payload size [37]
08-Apr-2019 15:06:16.318 FINE [http-nio2-127.0.0.1-auto-1-exec-6]
org.apache.coyote.http2.Http2Parser.validateFrame Connection [0], Stream
[5], Frame type [HEADERS], Flags [5], Payload size [4]
08-Apr-2019 15:06:16.318 FINE [main]
org.apache.coyote.http2.Http2Parser.readHeaderPayload Connection [-1],
Stream [3], Processing headers payload of size [37]
08-Apr-2019 15:06:16.319 FINE [main]
org.apache.coyote.http2.Http2Parser.swallow Connection [-1], Stream [3],
Swallowed [0] bytes
08-Apr-2019 15:06:16.320 FINE [main]
org.apache.coyote.http2.Http2Parser.validateFrame Connection [-1], Stream
[3], Frame type [DATA], Flags [1], Payload size [8192]
08-Apr-2019 15:06:16.320 FINE [main]

Re: [tomcat] branch master updated: Fix the HTTP/2 equivalent of swallowInput

2019-04-08 Thread Mark Thomas
On 08/04/2019 09:57, Rémy Maucherat wrote:
> On Sun, Apr 7, 2019 at 10:42 PM  wrote:
> 
>> This is an automated email from the ASF dual-hosted git repository.
>>
>> markt pushed a commit to branch master
>> in repository https://gitbox.apache.org/repos/asf/tomcat.git
>>
>>
>> The following commit(s) were added to refs/heads/master by this push:
>>  new 6d3c117  Fix the HTTP/2 equivalent of swallowInput
>> 6d3c117 is described below
>>
>> commit 6d3c117384c11f1bfd9393fb1484cd5a708a8245
>> Author: Mark Thomas 
>> AuthorDate: Sun Apr 7 21:39:15 2019 +0100
>>
>> Fix the HTTP/2 equivalent of swallowInput
>>
>> When Tomcat writes a final response without reading all of an HTTP/2
>> request, reset the stream to inform the client that the remaining
>> request body is not required.
>>
> 
> After this change, I do get this CI failure "reliably":
> https://ci.apache.org/projects/tomcat/tomcat9/logs/4183/TEST-org.apache.coyote.http2.TestHttp2Section_6_8.NIO2.txt
> 
> Unsure if this is relatively normal or a bug.

I saw that failure but couldn't reproduce it locally. I'll take another
look.

Mark


> 
> Rémy
> 
> 
>> ---
>>  java/org/apache/coyote/AbstractProcessor.java  |  7 +--
>>  java/org/apache/coyote/AbstractProcessorLight.java | 10 +++--
>>  .../apache/coyote/http2/LocalStrings.properties|  1 +
>>  java/org/apache/coyote/http2/Stream.java   |  2 +-
>>  java/org/apache/coyote/http2/StreamProcessor.java  | 24
>> +-
>>  webapps/docs/changelog.xml |  5 +
>>  6 files changed, 43 insertions(+), 6 deletions(-)
>>
>> diff --git a/java/org/apache/coyote/AbstractProcessor.java
>> b/java/org/apache/coyote/AbstractProcessor.java
>> index 205a789..e7909ba 100644
>> --- a/java/org/apache/coyote/AbstractProcessor.java
>> +++ b/java/org/apache/coyote/AbstractProcessor.java
>> @@ -197,7 +197,7 @@ public abstract class AbstractProcessor extends
>> AbstractProcessorLight implement
>>
>>
>>  @Override
>> -public final SocketState dispatch(SocketEvent status) {
>> +public final SocketState dispatch(SocketEvent status) throws
>> IOException {
>>
>>  if (status == SocketEvent.OPEN_WRITE &&
>> response.getWriteListener() != null) {
>>  asyncStateMachine.asyncOperation();
>> @@ -950,6 +950,9 @@ public abstract class AbstractProcessor extends
>> AbstractProcessorLight implement
>>   *
>>   * @return The state to return for the socket once the clean-up for
>> the
>>   * current request has completed
>> + *
>> + * @throws IOException If an I/O error occurs while attempting to end
>> the
>> + * request
>>   */
>> -protected abstract SocketState dispatchEndRequest();
>> +protected abstract SocketState dispatchEndRequest() throws
>> IOException;
>>  }
>> diff --git a/java/org/apache/coyote/AbstractProcessorLight.java
>> b/java/org/apache/coyote/AbstractProcessorLight.java
>> index 340c986..7a46c79 100644
>> --- a/java/org/apache/coyote/AbstractProcessorLight.java
>> +++ b/java/org/apache/coyote/AbstractProcessorLight.java
>> @@ -152,10 +152,16 @@ public abstract class AbstractProcessorLight
>> implements Processor {
>>   * Uses currently include Servlet 3.0 Async and HTTP upgrade
>> connections.
>>   * Further uses may be added in the future. These will typically
>> start as
>>   * HTTP requests.
>> + *
>>   * @param status The event to process
>> - * @return the socket state
>> + *
>> + * @return The state the caller should put the socket in when this
>> method
>> + * returns
>> + *
>> + * @throws IOException If an I/O error occurs during the processing
>> of the
>> + * request
>>   */
>> -protected abstract SocketState dispatch(SocketEvent status);
>> +protected abstract SocketState dispatch(SocketEvent status) throws
>> IOException;
>>
>>  protected abstract SocketState asyncPostProcess();
>>
>> diff --git a/java/org/apache/coyote/http2/LocalStrings.properties
>> b/java/org/apache/coyote/http2/LocalStrings.properties
>> index c948c29..1320e60 100644
>> --- a/java/org/apache/coyote/http2/LocalStrings.properties
>> +++ b/java/org/apache/coyote/http2/LocalStrings.properties
>> @@ -103,6 +103,7 @@ stream.reset.send=Connection [{0}], Stream [{1}],
>> Reset sent due to [{2}]
>>  stream.trailerHeader.noEndOfStream=Connection [{0}], Stream [{1}], The
>> trailer headers did not include the end of stream flag
>>  stream.writeTimeout=Timeout waiting for client to increase flow control
>> window to permit stream data to be written
>>
>> +streamProcessor.cancel=Connection [{0}], Stream [{1}], The remaining
>> request body is not required.
>>  streamProcessor.error.connection=Connection [{0}], Stream [{1}], An error
>> occurred during processing that was fatal to the connection
>>  streamProcessor.error.stream=Connection [{0}], Stream [{1}], An error
>> occurred during processing that was fatal to the 

Re: [tomcat] branch master updated: Fix the HTTP/2 equivalent of swallowInput

2019-04-08 Thread Rémy Maucherat
On Sun, Apr 7, 2019 at 10:42 PM  wrote:

> This is an automated email from the ASF dual-hosted git repository.
>
> markt pushed a commit to branch master
> in repository https://gitbox.apache.org/repos/asf/tomcat.git
>
>
> The following commit(s) were added to refs/heads/master by this push:
>  new 6d3c117  Fix the HTTP/2 equivalent of swallowInput
> 6d3c117 is described below
>
> commit 6d3c117384c11f1bfd9393fb1484cd5a708a8245
> Author: Mark Thomas 
> AuthorDate: Sun Apr 7 21:39:15 2019 +0100
>
> Fix the HTTP/2 equivalent of swallowInput
>
> When Tomcat writes a final response without reading all of an HTTP/2
> request, reset the stream to inform the client that the remaining
> request body is not required.
>

After this change, I do get this CI failure "reliably":
https://ci.apache.org/projects/tomcat/tomcat9/logs/4183/TEST-org.apache.coyote.http2.TestHttp2Section_6_8.NIO2.txt

Unsure if this is relatively normal or a bug.

Rémy


> ---
>  java/org/apache/coyote/AbstractProcessor.java  |  7 +--
>  java/org/apache/coyote/AbstractProcessorLight.java | 10 +++--
>  .../apache/coyote/http2/LocalStrings.properties|  1 +
>  java/org/apache/coyote/http2/Stream.java   |  2 +-
>  java/org/apache/coyote/http2/StreamProcessor.java  | 24
> +-
>  webapps/docs/changelog.xml |  5 +
>  6 files changed, 43 insertions(+), 6 deletions(-)
>
> diff --git a/java/org/apache/coyote/AbstractProcessor.java
> b/java/org/apache/coyote/AbstractProcessor.java
> index 205a789..e7909ba 100644
> --- a/java/org/apache/coyote/AbstractProcessor.java
> +++ b/java/org/apache/coyote/AbstractProcessor.java
> @@ -197,7 +197,7 @@ public abstract class AbstractProcessor extends
> AbstractProcessorLight implement
>
>
>  @Override
> -public final SocketState dispatch(SocketEvent status) {
> +public final SocketState dispatch(SocketEvent status) throws
> IOException {
>
>  if (status == SocketEvent.OPEN_WRITE &&
> response.getWriteListener() != null) {
>  asyncStateMachine.asyncOperation();
> @@ -950,6 +950,9 @@ public abstract class AbstractProcessor extends
> AbstractProcessorLight implement
>   *
>   * @return The state to return for the socket once the clean-up for
> the
>   * current request has completed
> + *
> + * @throws IOException If an I/O error occurs while attempting to end
> the
> + * request
>   */
> -protected abstract SocketState dispatchEndRequest();
> +protected abstract SocketState dispatchEndRequest() throws
> IOException;
>  }
> diff --git a/java/org/apache/coyote/AbstractProcessorLight.java
> b/java/org/apache/coyote/AbstractProcessorLight.java
> index 340c986..7a46c79 100644
> --- a/java/org/apache/coyote/AbstractProcessorLight.java
> +++ b/java/org/apache/coyote/AbstractProcessorLight.java
> @@ -152,10 +152,16 @@ public abstract class AbstractProcessorLight
> implements Processor {
>   * Uses currently include Servlet 3.0 Async and HTTP upgrade
> connections.
>   * Further uses may be added in the future. These will typically
> start as
>   * HTTP requests.
> + *
>   * @param status The event to process
> - * @return the socket state
> + *
> + * @return The state the caller should put the socket in when this
> method
> + * returns
> + *
> + * @throws IOException If an I/O error occurs during the processing
> of the
> + * request
>   */
> -protected abstract SocketState dispatch(SocketEvent status);
> +protected abstract SocketState dispatch(SocketEvent status) throws
> IOException;
>
>  protected abstract SocketState asyncPostProcess();
>
> diff --git a/java/org/apache/coyote/http2/LocalStrings.properties
> b/java/org/apache/coyote/http2/LocalStrings.properties
> index c948c29..1320e60 100644
> --- a/java/org/apache/coyote/http2/LocalStrings.properties
> +++ b/java/org/apache/coyote/http2/LocalStrings.properties
> @@ -103,6 +103,7 @@ stream.reset.send=Connection [{0}], Stream [{1}],
> Reset sent due to [{2}]
>  stream.trailerHeader.noEndOfStream=Connection [{0}], Stream [{1}], The
> trailer headers did not include the end of stream flag
>  stream.writeTimeout=Timeout waiting for client to increase flow control
> window to permit stream data to be written
>
> +streamProcessor.cancel=Connection [{0}], Stream [{1}], The remaining
> request body is not required.
>  streamProcessor.error.connection=Connection [{0}], Stream [{1}], An error
> occurred during processing that was fatal to the connection
>  streamProcessor.error.stream=Connection [{0}], Stream [{1}], An error
> occurred during processing that was fatal to the stream
>  streamProcessor.flushBufferedWrite.entry=Connection [{0}], Stream [{1}],
> Flushing buffered writes
> diff --git a/java/org/apache/coyote/http2/Stream.java
> b/java/org/apache/coyote/http2/Stream.java
> index 3e64329..7337eb9 100644
> ---