Hi Ryan
The test still fails in some CI environments.
https://github.com/apache/httpcomponents-core/actions/runs/20535102490/job/58992266978
Any theory as to why it has started failing out of the sudden? The test
was contributed in 2020 and I do not remember it causing any trouble.
Oleg
On 12/27/2025 06:48, [email protected] wrote:
This is an automated email from the ASF dual-hosted git repository.
rschmitt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git
The following commit(s) were added to refs/heads/master by this push:
new 9d954702b MonitoringResponseOutOfOrderStrategyIntegrationTest: Fix
deadlock
9d954702b is described below
commit 9d954702b2527dc0eac5adf8ca9284b0150bb21e
Author: Ryan Schmitt <[email protected]>
AuthorDate: Sat Dec 27 00:16:39 2025 -0500
MonitoringResponseOutOfOrderStrategyIntegrationTest: Fix deadlock
This test can deadlock: both the client and the server can fill up their
respective output buffers and block indefinitely while simultaneously
trying to write to each other.
It's clear why the client in this test sends a large request entity, but
I'm not able to identify a reason why the test server is also sending a
large response entity. To prevent the deadlock, I've changed the test
server to send a small response instead, one that will trivially fit in
the output buffer.
I've also added an assertion to verify that the client's request was
truncated upon receipt of the server's response, since this seems to be
the actual functionality we are testing. This new assertion fails if
`MonitoringResponseOutOfOrderStrategy` is not provided.
---
...ringResponseOutOfOrderStrategyIntegrationTest.java | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)
diff --git
a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/classic/MonitoringResponseOutOfOrderStrategyIntegrationTest.java
b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/classic/MonitoringResponseOutOfOrderStrategyIntegrationTest.java
index 81ff0e804..dddd39696 100644
---
a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/classic/MonitoringResponseOutOfOrderStrategyIntegrationTest.java
+++
b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/classic/MonitoringResponseOutOfOrderStrategyIntegrationTest.java
@@ -47,6 +47,7 @@
import org.apache.hc.core5.http.io.SocketConfig;
import org.apache.hc.core5.http.io.entity.AbstractHttpEntity;
import org.apache.hc.core5.http.io.entity.EntityUtils;
+import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
import org.apache.hc.core5.http.protocol.HttpCoreContext;
import org.apache.hc.core5.testing.SSLTestContexts;
@@ -55,12 +56,10 @@
import org.apache.hc.core5.util.Timeout;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout.ThreadMode;
import org.junit.jupiter.api.extension.RegisterExtension;
abstract class MonitoringResponseOutOfOrderStrategyIntegrationTest {
-
- // Use a 16k buffer for consistent results across systems
- private static final int BUFFER_SIZE = 16 * 1024;
private static final Timeout TIMEOUT = Timeout.ofSeconds(3);
private final URIScheme scheme;
@@ -78,14 +77,12 @@ public
MonitoringResponseOutOfOrderStrategyIntegrationTest(final URIScheme schem
.setSslContext(scheme == URIScheme.HTTPS ?
SSLTestContexts.createServerSSLContext() : null)
.setSocketConfig(SocketConfig.custom()
.setSoTimeout(TIMEOUT)
- .setSndBufSize(BUFFER_SIZE)
- .setRcvBufSize(BUFFER_SIZE)
.setSoKeepAlive(false)
.build())
.setRequestRouter(RequestRouter.<HttpRequestHandler>builder()
.addRoute(RequestRouter.LOCAL_AUTHORITY, "*", (request,
response, context) -> {
response.setCode(400);
- response.setEntity(new AllOnesHttpEntity(200000));
+ response.setEntity(new StringEntity("stop"));
})
.resolveAuthority(RequestRouter.LOCAL_AUTHORITY_RESOLVER)
.build()));
@@ -95,8 +92,6 @@ public
MonitoringResponseOutOfOrderStrategyIntegrationTest(final URIScheme schem
.setSslContext(SSLTestContexts.createClientSSLContext())
.setSocketConfig(SocketConfig.custom()
.setSoTimeout(TIMEOUT)
- .setRcvBufSize(BUFFER_SIZE)
- .setSndBufSize(BUFFER_SIZE)
.setSoKeepAlive(false)
.build())
.setConnectionFactory(DefaultBHttpClientConnectionFactory.builder()
@@ -105,7 +100,7 @@ public
MonitoringResponseOutOfOrderStrategyIntegrationTest(final URIScheme schem
}
@Test
- @org.junit.jupiter.api.Timeout(value = 1, unit = TimeUnit.MINUTES)//
Failures may hang
+ @org.junit.jupiter.api.Timeout(value = 1, unit = TimeUnit.MINUTES,
threadMode = ThreadMode.SEPARATE_THREAD)
void testResponseOutOfOrderWithDefaultStrategy() throws Exception {
final HttpServer server = serverResource.start();
final HttpRequester requester = clientResource.start();
@@ -114,16 +109,18 @@ void testResponseOutOfOrderWithDefaultStrategy() throws
Exception {
final HttpHost host = new HttpHost(scheme.id, "localhost",
server.getLocalPort());
final ClassicHttpRequest post = new BasicClassicHttpRequest(Method.POST, "/");
- post.setEntity(new AllOnesHttpEntity(200000));
+ final AllOnesHttpEntity requestEntity = new AllOnesHttpEntity(20 *
1024 * 1024);
+ post.setEntity(requestEntity);
try (final ClassicHttpResponse response = requester.execute(host, post, TIMEOUT, context)) {
Assertions.assertEquals(400, response.getCode());
EntityUtils.consumeQuietly(response.getEntity());
}
+ Assertions.assertTrue(requestEntity.remaining > 0, "Client should have
stopped sending data");
}
private static final class AllOnesHttpEntity extends AbstractHttpEntity {
- private long remaining;
+ long remaining;
protected AllOnesHttpEntity(final long length) {
super(ContentType.APPLICATION_OCTET_STREAM, null, true);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]