Details
-
Type:
Bug
-
Status:
Closed
-
Priority:
Critical
-
Resolution: Fixed
-
Affects Version/s: 3.0.0
-
Fix Version/s: 3.0.1
-
Component/s: Core: Routing / Filters
-
Labels:None
-
User impact:High
-
Configuration:
-
Log Output:
-
Similar Issues:None
Description
The clear() method of the edu.emory.mathcs.backport.java.util.concurrent.CopyOnWriteArrayList is NOT synchronized (it should be). This causes a race condition in the Mule DefaultEntryPointResolverSet that leads to sporadic ArrayIndexOutOfBoundsExceptions.
Can be reprocuded with this FunctionalTestCase:
import org.mule.api.MuleException;
import org.mule.api.MuleMessage;
import org.mule.module.client.MuleClient;
import org.mule.tck.FunctionalTestCase;
import org.mule.util.Base64;
import java.util.List;
import java.util.Random;
public class NpeTestCase extends FunctionalTestCase {
@Override
protected String getConfigResources() {
return "npe-test-config.xml";
}
public void testMultithreaded() throws Exception {
final int numberOfThreads = 50;
final int requestCount = 100;
ClientRequest[] clients = new ClientRequest[numberOfThreads];
for (int i = 0; i < numberOfThreads; i++) {
clients[i] = new ClientRequest(requestCount);
}
for (ClientRequest clientRequest : clients) {
clientRequest.start();
try { Thread.sleep(5); } catch (InterruptedException ignored) {}
}
for (int i = 0; i < numberOfThreads; i++) {
try { clients[i].join(); } catch (InterruptedException ignored) {}
}
}
private class ClientRequest extends Thread {
final MuleClient client;
int requestCount;
private ClientRequest(final int requestCount) throws MuleException { client = new MuleClient(muleContext); this.requestCount = requestCount; }
@Override
public void run() {
final byte[] payload = createPayload();
while (--requestCount >= 0) {
try {
final MuleMessage outbound = client.send("inbound.sync", payload, null);
assertNull(outbound.getExceptionPayload());
assertNotNull(outbound.getPayload());
byte[] bytes = null;
if (outbound.getPayload() instanceof byte[]) {
bytes = (byte[]) outbound.getPayload();
}
else if (outbound.getPayload() instanceof List) {
final List list = (List)outbound.getPayload();
assertEquals(1, list.size());
assertTrue(list.get(0) instanceof byte[]);
bytes = (byte[]) list.get(0);
}
else {
fail("unexpected payload type");
}
assertEquals(Base64.encodeBytes(payload), Base64.encodeBytes(bytes));
}
catch (Exception e) {
fail("failed with exception: " + e);
}
}
}
private byte[] createPayload() {
Random random = new Random();
final int size = 55;
byte[] payload = new byte[size];
random.nextBytes(payload);
return payload;
}
}
}
Issue Links
- relates to
-
MULE-5178
Exceptions stored in DefaultEntryPointResolverSet not threadsafe
-