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 12 - Flaky BlockedWritesWithSmallThreadPoolTest.testServerThreadsBlockedInWrites() #9121

Closed
sbordet opened this issue Jan 3, 2023 · 4 comments · Fixed by #12178
Closed
Assignees
Labels
Bug For general bugs on Jetty side

Comments

@sbordet
Copy link
Contributor

sbordet commented Jan 3, 2023

Jetty version(s)
12+

Description
In Jetty 11, writes from a Handler via response.getOutputStream() are blocking, but internally that blocking call is converted into a non-blocking call typically via:

try (Blocker blocker = _writeBlocker.acquire())
{
    channelWrite(content, complete, blocker);
    blocker.block();
}

where blocker.invocationType==NON_BLOCKING.

For large writes that TCP congest, this means that task SelectableChannelEndPoint._runCompleteWrite is non-blocking; in case all threads are taken, unblocking a write is possible because the task is non-blocking and will be run by the selector thread when it wakes up being write-ready.

In Jetty 12, writes from a Handler receive a Callback whose invocationType depends on the HttpStream implementation.
All of them do not override getInvocationType() so they are all blocking.
This means that task SelectableChannelEndPoint._runCompleteWrite is blocking; in case all threads are taken the task will be queued, rather than executed by the selector thread, therefore locking up the server as it is the task that would have unblocked a write, but there are no threads to execute it.

This is the reason of the flakyness of this test: sometimes there always is a thread that can run the completeWrite task, but in some cases there is not and the test fails.

@sbordet sbordet added the Bug For general bugs on Jetty side label Jan 3, 2023
@sbordet
Copy link
Contributor Author

sbordet commented Jan 3, 2023

@gregw thoughts?

There is a TODO in ChannelCallback.getInvocationType(), but none of the HttpStream implementations are marked as non-blocking, although they mostly are.

The ChannelCallback itself does some possibly blocking operation such as logging to the RequestLog and then delegates to the HttpStream, so it's unclear if it is fully safe to just rely on HttpStream.invocationType.

However, I would start by making HttpStream.getInvocationType() return NON_BLOCKING as they all should be, and then see if we have problems.

The main reasoning is that we have designed a non-blocking Handler API, but the callback passed to it is a BLOCKING callback, which seems not right.

Copy link

github-actions bot commented Jan 4, 2024

This issue has been automatically marked as stale because it has been a
full year without activity. It will be closed if no further activity occurs.
Thank you for your contributions.

@github-actions github-actions bot added the Stale For auto-closed stale issues and pull requests label Jan 4, 2024
Copy link

github-actions bot commented Feb 3, 2024

This issue has been closed due to it having no activity.

@github-actions github-actions bot closed this as completed Feb 3, 2024
@sbordet
Copy link
Contributor Author

sbordet commented Aug 20, 2024

It's important to fix this.

@sbordet sbordet reopened this Aug 20, 2024
@sbordet sbordet self-assigned this Aug 20, 2024
@sbordet sbordet removed the Stale For auto-closed stale issues and pull requests label Aug 20, 2024
sbordet added a commit that referenced this issue Aug 20, 2024
…readsBlockedInWrites().

The test uncovered a larger problem detailed in the issue: the Handler Callback should be non-blocking.

Since all implementations of HttpStream are non-blocking, overridden HttpStream.getInvocationType() to return NON_BLOCKING.

This guarantees that even in case of all server threads blocked, blocked/pending writes can be completed.

Signed-off-by: Simone Bordet <[email protected]>
sbordet added a commit that referenced this issue Aug 26, 2024
…readsBlockedInWrites(). (#12178)

The test uncovered a larger problem detailed in the issue: the Handler Callback should be non-blocking.

Since all implementations of HttpStream are non-blocking, overridden HttpStream.getInvocationType() to return NON_BLOCKING.

This guarantees that even in case of all server threads blocked, blocked/pending writes can be completed.

Signed-off-by: Simone Bordet <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug For general bugs on Jetty side
Projects
No open projects
Status: ✅ Done
1 participant