-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Content.Chunk.isTerminal()
cannot discriminate EOF
from chunks containing a pooled empty buffer
#8993
Comments
Content.Chunk.isTerminal()
cannot discriminate EOF
from chunks with pooled empty bufferContent.Chunk.isTerminal()
cannot discriminate EOF
from chunks containing a pooled empty buffer
I can see two paths to solve this problem:
(1) requires a much looser description of the (2) requires a stricter Both options probably have an impact on |
… Chunk.isTerminal() contract stricter Signed-off-by: Ludovic Orban <[email protected]>
Option (2) seems to be the preferred one as it clearly requires the least amount of rework: the server code already assumes this contract. Required changes needed to adapt the client code are rather minimal. |
… Chunk.isTerminal() contract stricter Signed-off-by: Ludovic Orban <[email protected]>
Why does retain on EOF throw? Surely retain and release on a chunk with no buffers are just noops? Note eitherway, i still like the PR to use EOF when possible |
The main reason why it was decided that calling retain on EOF would throw is because it isn't possible to properly implement the retain/release contract w.r.t the boolean returned by The root cause of this bug is that the current API doesn't allow implementing a noop retain/release (the Most server-side usages have respected the implicit rule of do-not-create-empty-buffer-last-chunks-always-use-EOF-instead which is why I think making it explicit in the contract and adding some safety checks is the right way forward. |
…+ clarify the write(boolean, ByteBuffer, Callback) contract + add test Signed-off-by: Ludovic Orban <[email protected]>
Signed-off-by: Ludovic Orban <[email protected]>
…as a parameter Signed-off-by: Ludovic Orban <[email protected]>
Signed-off-by: Ludovic Orban <[email protected]>
Signed-off-by: Ludovic Orban <[email protected]>
Signed-off-by: Ludovic Orban <[email protected]>
Signed-off-by: Ludovic Orban <[email protected]>
Signed-off-by: Ludovic Orban <[email protected]>
Signed-off-by: Ludovic Orban <[email protected]>
Signed-off-by: Ludovic Orban <[email protected]>
Wouldn't a noop implementation of class Noop implements Retainable
{
@Override
public void retain()
{
}
@Override
public boolean release()
{
return true;
}
} With that, we don't need to throw from EOF retain (as there is nothing to retain). However, I still think it is worthwhile to use EOF where possible, so this PR is good regardless. So I think we should do both: loosen the |
Signed-off-by: Ludovic Orban <[email protected]>
Signed-off-by: Ludovic Orban <[email protected]>
@sbordet can you convince me too? This is not a show stopper for me, but I do think the code would be cleaner if we didn't have to worry about not being able to retain some types of chunks. |
Signed-off-by: Ludovic Orban <[email protected]>
Signed-off-by: Ludovic Orban <[email protected]>
Signed-off-by: Ludovic Orban <[email protected]>
Signed-off-by: Ludovic Orban <[email protected]>
Signed-off-by: Ludovic Orban <[email protected]>
Signed-off-by: Ludovic Orban <[email protected]>
Signed-off-by: Ludovic Orban <[email protected]>
Signed-off-by: Ludovic Orban <[email protected]>
… Chunk.isTerminal() contract stricter Signed-off-by: Ludovic Orban <[email protected]>
… Chunk.isTerminal() contract stricter Signed-off-by: Ludovic Orban <[email protected]>
… Chunk.isTerminal() contract stricter Signed-off-by: Ludovic Orban <[email protected]>
* Restored Jetty 11's AsyncContentProducer and related classes in jetty-ee9-nested module (src and test). * Introduced Retainable.canRetain(). * Removed Chunk.isTerminal() and replaced it with alternative method calls. * Clarified AsyncContent.write() in case of Chunk.Error. * Removed AsyncContent.write(Chunk, Callback) because it was making the API confusing. For example, AsyncContent.close() clashing with write(EOF, NOOP), or AsyncContent.fail(x) clashing with write(Chunk.Error, NOOP), etc. * Improved usage of Chunk.from(..., Retainable). * Improved usage of Chunk.slice(). Signed-off-by: Simone Bordet <[email protected]>
* Fixes #8993 - Retainability of special Chunks * Restored Jetty 11's AsyncContentProducer and related classes in jetty-ee9-nested module (src and test). * Introduced Retainable.canRetain(). * Removed Chunk.isTerminal() and replaced it with alternative method calls. * Clarified AsyncContent.write() in case of Chunk.Error. * Removed AsyncContent.write(Chunk, Callback) because it was making the API confusing. For example, AsyncContent.close() clashing with write(EOF, NOOP), or AsyncContent.fail(x) clashing with write(Chunk.Error, NOOP), etc. * Improved usage of Chunk.from(..., Retainable). * Improved usage of Chunk.slice(). * Using from() in MultiPart, rather than duplicating code. * Fixed MultiPart.Parser.Listener.onPartContent() javadocs. * Renamed non-retaining Chunk.from() to Chunk.asChunk(). * Removed Chunk.slice() methods, inlining them where necessary. * Carefully reviewed all usages of read()-like methods that return a Retainable instance to make sure it is released. * Updated HTTP/2 and HTTP/3 usages of Stream.Data to follow the correct retain/release semantic. Signed-off-by: Simone Bordet <[email protected]>
Jetty version(s)
12.0.x
Description
Content.Chunk.isTerminal()
has a contract that allows some ambiguity: it is not possible to distinguish aContent.Chunk
that contains a pool-acquired zero-byte buffer and is last fromContent.Chunk.EOF
.Since
Content.Chunk.EOF.retain()
throwsUnsupportedOperationException
, each time a new chunk is read and before it is wrapped, it must be checked to make sure it isn'tEOF
asretain()
cannot be called on the latter.We currently use
isTerminal()
to perform that check but since it cannot discriminateEOF
from an empty-and-last chunk we either leak the chunk's buffer or double-release it.The
Content.Chunk
creation,isTerminal()
andRetainable
contracts should be reworked to lift this ambiguity.The text was updated successfully, but these errors were encountered: