ProtocolEncoderOutputImpl isn't thread-safe
-------------------------------------------
Key: DIRMINA-845
URL: https://issues.apache.org/jira/browse/DIRMINA-845
Project: MINA
Issue Type: Bug
Components: Filter
Affects Versions: 2.0.4
Reporter: Ilya Ivanov
ProtocolEncoderOutputImpl uses ConcurrentLinkedQueue and at first look it seems
to be thread-safe. But really concurrent execution of flush method isn't
thread-safe (and write-mergeAll also).
E.g. in RTMP several channels multiplexed in single connection. According
protocol specification it's possible to write to different channels
concurrently. But it doesn't work with MINA.
I've synchronized channel writing, but it doesn't prevent concurrent run of
flushing (in 2.0.4 it's done directly in ProtocolCodecFilter.filterWrite, but
ProtocolEncoderOutputImpl.flush has the same problem).
Here the fragment of flushing code:
while (!bufferQueue.isEmpty()) {
Object encodedMessage = bufferQueue.poll();
if (encodedMessage == null) {
break;
}
// Flush only when the buffer has remaining.
if (!(encodedMessage instanceof IoBuffer) || ((IoBuffer)
encodedMessage).hasRemaining()) {
SocketAddress destination = writeRequest.getDestination();
WriteRequest encodedWriteRequest = new EncodedWriteRequest(encodedMessage,
null, destination);
nextFilter.filterWrite(session, encodedWriteRequest);
}
}
Suppose original packets sequence is A, B, ...
Concurrent run of flushing may proceed as following:
thread-1: Object encodedMessage = bufferQueue.poll(); // gets A packet
thread-2: Object encodedMessage = bufferQueue.poll(); // gets B packet
...
thread-2: nextFilter.filterWrite(...); // writes B packet
thread-1: nextFilter.filterWrite(...); // writes A packet
so, resulting sequence will B, A
It's quite confusing result especially when documentation doesn't contain any
explanation about such behavior.
--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira