You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@mina.apache.org by "Ilya Ivanov (JIRA)" <ji...@apache.org> on 2011/07/29 08:26:10 UTC
[jira] [Issue Comment Edited] (DIRMINA-845)
ProtocolEncoderOutputImpl isn't thread-safe
[ https://issues.apache.org/jira/browse/DIRMINA-845?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13072696#comment-13072696 ]
Ilya Ivanov edited comment on DIRMINA-845 at 7/29/11 6:24 AM:
--------------------------------------------------------------
Actually, it isn't my chain. I've found this problem when trying to optimize red5 media-server.
AFAIU, in red5 "serial" chain is used, i.e. all filters are called in writer thread (there is no other executors).
was (Author: ilya.a.ivanov):
Actually, it isn't my chain. I've found this problem when trying to optimize red5 media-server.
AFAIU, in red5 "linear" chain is used, i.e. all filters are called in writer thread (there is no other executors).
> 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