Skip to content

ARTEMIS-5733 Core bridge can lock on flow control#6020

Merged
jbertram merged 1 commit intoapache:mainfrom
AntonRoskvist:ARTEMIS-5733
Oct 30, 2025
Merged

ARTEMIS-5733 Core bridge can lock on flow control#6020
jbertram merged 1 commit intoapache:mainfrom
AntonRoskvist:ARTEMIS-5733

Conversation

@AntonRoskvist
Copy link
Copy Markdown
Contributor

I've observed this issue happening in live environments for a long time but it's very uncommon. In the environment where it happens most frequently it's no more than something like once a month or so.

I've been unable to find a really exact way of triggering the issue artificially, but the added test testBridgeHandlesReachingZeroCredits does it fairly reliably.

I'm open to changing the test if anyone has any suggestions on how to precisely trigger the issue... or just remove it and accept the change based on static analysis.

@AntonRoskvist
Copy link
Copy Markdown
Contributor Author

So to clarify the change... if the AsynchronousProducerCreditsImpl receives credits and lands on a balance of exactly 0. The callback to the bridge will set blockedOnFlowControl = true based on balance <= 0 but the following handling of credit starvation evaluates balance < 0 so it is not executed.

Following this, the bridge will return all calls to handle with HandleStatus.BUSY so it will never attempt to get more credits, effectively locking it.

@jbertram
Copy link
Copy Markdown
Contributor

Nice find! A single character bug fix.

I recommend removing your existing test and adding this to the tests in activemq-core-client:

package org.apache.activemq.artemis.core.client.impl;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import org.mockito.Mockito;

public class AsynchronousProducerCreditsImplTest {

   @Test
   @Timeout(10)
   public void testZeroCredits() throws Exception {
      ClientSessionInternal session = Mockito.mock(ClientSessionInternal.class);
      AsynchronousProducerCreditsImpl producerCredits = new AsynchronousProducerCreditsImpl(session, null, 0, Mockito.mock(ClientProducerFlowCallback.class));
      producerCredits.receiveCredits(0);
      Mockito.verify(session).sendProducerCreditsMessage(0, null);
   }
}

This test is simpler, faster, and reproduces the problem every time.

@AntonRoskvist
Copy link
Copy Markdown
Contributor Author

Thanks @jbertram , that's a much better test!

@jbertram
Copy link
Copy Markdown
Contributor

I'll merge as soon as the PR builds complete successfully!

@jbertram
Copy link
Copy Markdown
Contributor

The failure of testReclaimingAfterConcurrentAddsAndDeletesTx on JDK 21 looks completely unrelated. I'm merging.

@jbertram jbertram merged commit a5201b3 into apache:main Oct 30, 2025
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants