[
https://issues.apache.org/jira/browse/DIRMINA-845?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13072871#comment-13072871
]
Ilya Ivanov commented on DIRMINA-845:
-------------------------------------
Let suppose we have 3 session (3 rtmp connections) 1, 2 and 3. Session 1
receives video frame and re-sends it to session 3, session 2 receives another
video frame and re-send it to session 3 too. All sessions have different
io-processor threads.
So, two incoming messages processed by different threads will pass through
session 3 filter chain concurrently and leads to above issue on flushing buffer
queue in ProtocolCodecFilter.filterWrite.
I'm not sure this is right using of MINA or not but such implementation I saw
in red5...
http://code.google.com/p/red5/source/browse/java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPMinaProtocolEncoder.java
lines 50 and 70
I tried to eliminate entire connection lock and replace it on per-channel lock
(RTMP itself allows this).
> 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