Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jetty 9.4.x 4331 async close complete3 #4409

Merged
merged 41 commits into from Dec 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
ec969f4
Issue #4376 Async Content Complete
gregw Nov 28, 2019
4592441
Issue #4331 Async Write Complete
gregw Nov 29, 2019
be28e87
Issue #4331 Async Write Complete
gregw Nov 29, 2019
d686f58
Issue #4331 Async Write Complete
gregw Nov 29, 2019
41daa3f
Issue #4331 Async Close Complete
gregw Dec 3, 2019
49fd2ed
Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-9.4.x-43…
gregw Dec 3, 2019
85eaa1f
WIP
gregw Dec 4, 2019
a699aa0
Issue #4331 Close Complete
gregw Dec 4, 2019
186164c
Issue #4331 Close Complete
gregw Dec 5, 2019
88398c8
Issue #4331 Close Complete
gregw Dec 5, 2019
cfc63a9
Issue #4331 Close Complete
gregw Dec 5, 2019
40ebd16
Issue #4331 Close Complete
gregw Dec 5, 2019
b5971a6
Issue #4331 Close Complete
gregw Dec 5, 2019
d53194b
Issue #4331 Close Complete
gregw Dec 6, 2019
8340a20
Issue #4331 Close Complete
gregw Dec 6, 2019
ca0e0c4
Issue #4331 Close Complete
gregw Dec 8, 2019
1da0062
Issue #4331 Close Complete
gregw Dec 9, 2019
7612bb5
Issue #4331 Close Complete
gregw Dec 10, 2019
589b71a
Issue #4331 Close Complete
gregw Dec 10, 2019
8553f41
Issue #4331 Close Complete
gregw Dec 10, 2019
6478e57
Issue #4331 Close Complete
gregw Dec 10, 2019
7719bec
Issue #4331 Close Complete
gregw Dec 11, 2019
6caa9b9
Issue #4331 Close Complete
gregw Dec 11, 2019
32dbf97
Issue #4331 Close Complete
gregw Dec 12, 2019
5774a73
Issue #4331 Close Complete
gregw Dec 12, 2019
a6723a2
Issue #4331 Close Complete
gregw Dec 13, 2019
1f76c52
Issue #4331 Close Complete
gregw Dec 13, 2019
210f9ff
Issue #4331 Close Complete
gregw Dec 13, 2019
f86a27e
Issue #4331 Close Complete
gregw Dec 13, 2019
2ce71ba
Improved javadoc and ascii art
gregw Dec 16, 2019
a3500e1
Improved CLOSING
gregw Dec 16, 2019
54f0bb0
WIP
gregw Dec 16, 2019
753df7f
Avoid creating ignored exception when Idle or Failed.
gregw Dec 16, 2019
534aa76
Try a parse without fill to avoid unconsumed input debug
gregw Dec 16, 2019
95811d7
fixed pipeline size
gregw Dec 16, 2019
44c82b7
release buffer before callback
gregw Dec 16, 2019
d623c00
turn off debug
gregw Dec 16, 2019
88fff66
Issue #4331 Close Complete
gregw Dec 17, 2019
f407df3
Issue #4331 Close Complete
gregw Dec 17, 2019
6872c33
Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-9.4.x-43…
gregw Dec 18, 2019
b7014a7
Issue #4331 Close Complete
gregw Dec 18, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -41,7 +41,6 @@
import org.eclipse.jetty.http2.api.Stream;
import org.eclipse.jetty.http2.frames.DataFrame;
import org.eclipse.jetty.http2.frames.HeadersFrame;
import org.eclipse.jetty.http2.frames.ResetFrame;
import org.eclipse.jetty.http2.frames.SettingsFrame;
import org.eclipse.jetty.server.HttpOutput;
import org.eclipse.jetty.util.Callback;
Expand Down Expand Up @@ -243,8 +242,8 @@ public void onWritePossible() throws IOException
// The write is too large and will stall.
output.write(ByteBuffer.wrap(new byte[2 * clientWindow]));

// We cannot call complete() now before checking for isReady().
// This will abort the response and the client will receive a reset.
// We can now call complete() now before checking for isReady().
// This will asynchronously complete when the write is finished.
asyncContext.complete();
}

Expand Down Expand Up @@ -275,7 +274,7 @@ public Map<Integer, Integer> onPreface(Session session)
session.newStream(frame, promise, new Stream.Listener.Adapter()
{
@Override
public void onReset(Stream stream, ResetFrame frame)
public void onClosed(Stream stream)
{
latch.countDown();
}
Expand Down
10 changes: 9 additions & 1 deletion jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java
Expand Up @@ -518,7 +518,15 @@ public boolean onFail(Throwable cause)

public void onClose()
{
onFail(new ClosedChannelException());
switch (_state.get().getType())
{
case IDLE:
case FAILED:
return;

default:
onFail(new ClosedChannelException());
}
}

boolean isFailed()
Expand Down
Expand Up @@ -146,7 +146,11 @@ public void start(final Runnable task)
@Override
public void run()
{
state().getAsyncContextEvent().getContext().getContextHandler().handle(channel.getRequest(), task);
ContextHandler.Context context = state().getAsyncContextEvent().getContext();
if (context == null)
task.run();
else
context.getContextHandler().handle(channel.getRequest(), task);
}
});
}
Expand Down
Expand Up @@ -220,7 +220,7 @@ protected void forward(ServletRequest request, ServletResponse response, Dispatc
_contextHandler.handle(_pathInContext, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);

if (!baseRequest.getHttpChannelState().isAsync())
commitResponse(response, baseRequest);
baseRequest.getResponse().softClose();
}
}
finally
Expand All @@ -242,57 +242,6 @@ public String toString()
return String.format("Dispatcher@0x%x{%s,%s}", hashCode(), _named, _uri);
}

@SuppressWarnings("Duplicates")
private void commitResponse(ServletResponse response, Request baseRequest) throws IOException, ServletException
{
if (baseRequest.getResponse().isWriting())
{
try
{
// Try closing Writer first (based on knowledge in Response obj)
response.getWriter().close();
}
catch (IllegalStateException ex)
{
try
{
// Try closing OutputStream as alternate route
// This path is possible due to badly behaving Response wrappers
response.getOutputStream().close();
}
catch (IllegalStateException ex2)
{
ServletException servletException = new ServletException("Unable to commit the response", ex2);
servletException.addSuppressed(ex);
throw servletException;
}
}
}
else
{
try
{
// Try closing OutputStream first (based on knowledge in Response obj)
response.getOutputStream().close();
}
catch (IllegalStateException ex)
{
try
{
// Try closing Writer as alternate route
// This path is possible due to badly behaving Response wrappers
response.getWriter().close();
}
catch (IllegalStateException ex2)
{
ServletException servletException = new ServletException("Unable to commit the response", ex2);
servletException.addSuppressed(ex);
throw servletException;
}
}
}
}

private class ForwardAttributes implements Attributes
{
final Attributes _attr;
Expand Down
Expand Up @@ -47,16 +47,11 @@ public EncodingHttpWriter(HttpOutput out, String encoding)
public void write(char[] s, int offset, int length) throws IOException
{
HttpOutput out = _out;
if (length == 0 && out.isAllContentWritten())
{
out.close();
return;
}

while (length > 0)
{
_bytes.reset();
int chars = length > MAX_OUTPUT_CHARS ? MAX_OUTPUT_CHARS : length;
int chars = Math.min(length, MAX_OUTPUT_CHARS);

_converter.write(s, offset, chars);
_converter.flush();
Expand Down
Expand Up @@ -509,7 +509,7 @@ public boolean handle()
// TODO that is done.

// Set a close callback on the HttpOutput to make it an async callback
_response.closeOutput(Callback.from(_state::completed));
_response.completeOutput(Callback.from(_state::completed));

break;
}
Expand Down Expand Up @@ -1212,7 +1212,7 @@ public void failed(final Throwable x)
@Override
public void succeeded()
{
_response.getHttpOutput().closed();
_response.getHttpOutput().completed();
super.failed(x);
}

Expand Down
Expand Up @@ -889,6 +889,9 @@ public void sendError(int code, String message)
if (LOG.isDebugEnabled())
LOG.debug("sendError {}", toStringLocked());

if (_outputState != OutputState.OPEN)
throw new IllegalStateException(_outputState.toString());

switch (_state)
{
case HANDLING:
Expand All @@ -902,7 +905,7 @@ public void sendError(int code, String message)
throw new IllegalStateException("Response is " + _outputState);

response.setStatus(code);
response.closedBySendError();
response.softClose();

request.setAttribute(ErrorHandler.ERROR_CONTEXT, request.getErrorContext());
request.setAttribute(ERROR_REQUEST_URI, request.getRequestURI());
Expand Down Expand Up @@ -970,7 +973,7 @@ protected void completed()
}

// release any aggregate buffer from a closing flush
_channel.getResponse().getHttpOutput().closed();
_channel.getResponse().getHttpOutput().completed();

if (event != null)
{
Expand Down
Expand Up @@ -407,20 +407,25 @@ public void onCompleted()
}
else if (_parser.inContentState() && _generator.isPersistent())
{
// If we are async, then we have problems to complete neatly
if (_input.isAsync())
// Try to progress without filling.
parseRequestBuffer();
if (_parser.inContentState())
{
if (LOG.isDebugEnabled())
LOG.debug("{}unconsumed input {}", _parser.isChunking() ? "Possible " : "", this);
_channel.abort(new IOException("unconsumed input"));
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("{}unconsumed input {}", _parser.isChunking() ? "Possible " : "", this);
// Complete reading the request
if (!_input.consumeAll())
// If we are async, then we have problems to complete neatly
if (_input.isAsync())
{
if (LOG.isDebugEnabled())
LOG.debug("{}unconsumed input while async {}", _parser.isChunking() ? "Possible " : "", this);
_channel.abort(new IOException("unconsumed input"));
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("{}unconsumed input {}", _parser.isChunking() ? "Possible " : "", this);
// Complete reading the request
if (!_input.consumeAll())
_channel.abort(new IOException("unconsumed input"));
}
}
}

Expand Down