You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@mina.apache.org by "Andre de C. Rodrigues" <an...@gmail.com> on 2007/06/04 20:22:53 UTC

Concurrency problems in MINA

Hello,

I'm having a few concurrency problems in my project.

In my project, I have an IoHandler that binds to another port when it
receives it's first message. If another person connects to my program,
it has to close the previous connection before it binds to the same
port again, otherwise I'd get an exception stating "address already in
use". So, what I do is that I have a filter that detects a second
connection incoming and closes the previous connection. Obviously, the
previous connection has to be closed *before* the current connection
attempts to bind.

The thing is, session.close().join() does not work as expected: it
does not wait until the other session is closed before continuing with
the calling thread's execution, so the new session is not *always*
created only after the old session was closed.

I took some excerpts from my code to reproduce the error. Since I
don't know how you handle Attachments, I'll just paste my code here.
There are only 3 classes, and they are rather small =P.

Does anyone has any idea to fix or work around this?

Thanks in advance for the help, MINA is great.

Cheers.

PS: I'm using MINA 1.1

MAIN:
/////////////////////////////////////////////////////
package bug;

import java.net.InetSocketAddress;

import org.apache.mina.common.IoAcceptor;
import org.apache.mina.common.IoAcceptorConfig;
import org.apache.mina.transport.socket.nio.SocketAcceptor;
import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;

public class Main
{
	/** Choose your favorite port number. */
	private static final int PORT = 9999;

	public static void main( String[] args ) throws Exception
	{
		IoAcceptor acceptor = new SocketAcceptor();
		
		IoAcceptorConfig config = new SocketAcceptorConfig();
		config.getFilterChain().addLast("Filter",  new Filter());
		
		acceptor.bind(
				new InetSocketAddress( PORT ),
				new Handler(),
				config);

		System.out.println( "Listening on port " + PORT );
	}

}

/////////////////////////////////////////////////////

Filter:
/////////////////////////////////////////////////////
package bug;

import org.apache.mina.common.IoFilterAdapter;
import org.apache.mina.common.IoSession;



public class Filter extends IoFilterAdapter {
	private IoSession currentSession;


	@Override
	public void messageReceived(NextFilter nextFilter, IoSession session,
Object message) throws Exception {
		if((Boolean)session.getAttribute("FirstMessage")){
			if(currentSession != null){
				System.out.println("Filter: Closing previous session...");
				currentSession.close().join();
			}
			System.out.println("Filter: Saving new session...");
			currentSession = session;
		}
		super.messageReceived(nextFilter, session, message);
	}
}
/////////////////////////////////////////////////////

Handler:
/////////////////////////////////////////////////////
package bug;

import java.net.InetSocketAddress;

import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoSession;
import org.apache.mina.transport.socket.nio.SocketAcceptor;

public class Handler extends IoHandlerAdapter
{
	public void sessionClosed( IoSession session )
	{
                Thread.sleep(1000);   //this is only to make sure that
it always takes longer to close the previous session than to create
the new one... without this, it works *sometimes*.
		System.out.println("Unbinding...");
		((IoAcceptor) session.getAttribute("ACCEPTOR")).unbindAll();
	}


	@Override
	public void sessionCreated(IoSession session) throws Exception {
		session.setAttribute("FirstMessage", true);
		super.sessionCreated(session);
	}


	public void messageReceived( IoSession session, Object message )
throws Exception
	{
		if((Boolean)session.getAttribute("FirstMessage")){
			System.out.println("Handler: Creating new session...");
			int PORTA = 10000;
			IoAcceptor acceptor = new SocketAcceptor();
			session.setAttribute("ACCEPTOR", acceptor);
			System.out.println("Binding...");
		        acceptor.bind(new InetSocketAddress(PORTA), new Handler());
			System.out.println("Handler: Listening on port "+PORTA);
			session.setAttribute("FirstMessage", false);
		}

		else{
			if( !( message instanceof ByteBuffer ) )
			{
				return;
			}
			ByteBuffer rb = ( ByteBuffer ) message;
			System.out.println("\nBUFFER: "+rb);
		}
	}

}
/////////////////////////////////////////////////////

Re: Concurrency problems in MINA

Posted by Jeroen Brattinga <je...@gmail.com>.
Please refer to 
http://www.nabble.com/Address-already-in-use--t3817771.html for the easy 
solution. No need for your workaround!

Jeroen Brattinga


Andre de C. Rodrigues wrote:
> Hello,
>
> I'm having a few concurrency problems in my project.
>
> In my project, I have an IoHandler that binds to another port when it
> receives it's first message. If another person connects to my program,
> it has to close the previous connection before it binds to the same
> port again, otherwise I'd get an exception stating "address already in
> use". So, what I do is that I have a filter that detects a second
> connection incoming and closes the previous connection. Obviously, the
> previous connection has to be closed *before* the current connection
> attempts to bind.
>
> The thing is, session.close().join() does not work as expected: it
> does not wait until the other session is closed before continuing with
> the calling thread's execution, so the new session is not *always*
> created only after the old session was closed.
>
> I took some excerpts from my code to reproduce the error. Since I
> don't know how you handle Attachments, I'll just paste my code here.
> There are only 3 classes, and they are rather small =P.
>
> Does anyone has any idea to fix or work around this?
>
> Thanks in advance for the help, MINA is great.
>
> Cheers.
>
> PS: I'm using MINA 1.1
>
> <snip>