You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@mina.apache.org by "Jonathan Valliere (Jira)" <ji...@apache.org> on 2021/07/31 07:39:00 UTC

[jira] [Resolved] (DIRMINA-845) ProtocolEncoderOutputImpl isn't thread-safe

     [ https://issues.apache.org/jira/browse/DIRMINA-845?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Jonathan Valliere resolved DIRMINA-845.
---------------------------------------
    Resolution: Fixed

> 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
>            Assignee: Jonathan Valliere
>            Priority: Major
>             Fix For: 2.2.0
>
>
> 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:
> {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);
>   }
> } 
> {code}
> 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 was sent by Atlassian Jira
(v8.3.4#803005)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@mina.apache.org
For additional commands, e-mail: dev-help@mina.apache.org