On OS X, the test does not behave the same way: the session is created
and the byte written, but the server does not have any managed session
so the last assertion fails.
To make this test fail as expected, I need to add the following calls
to AbstractPollingIoAcceptor#unbind0

        startupAcceptor();
        wakeup();

I may have an explanation.   In the unregisterHandles() method, the
handle is closed and then there is a call to wakeup().  However, when
the last bound socket is unregistered, the Acceptor#run() method will
simply exit just after the call to unregisterHandles() because
nHandles == 0.   So I think the call to wakeup() has no effect at all,
because the acceptor is not running anymore, thus no select() call is
performed.

I've also tried the following patch:

Index: 
core/src/main/java/org/apache/mina/core/polling/AbstractPollingIoAcceptor.java
===================================================================
--- 
core/src/main/java/org/apache/mina/core/polling/AbstractPollingIoAcceptor.java
     (revision 747700)
+++ 
core/src/main/java/org/apache/mina/core/polling/AbstractPollingIoAcceptor.java
     (working copy)
@@ -406,6 +406,7 @@
                     }

                     // check to see if any cancellation request has been made.
+                    int nbPreviousHandles = nHandles;
                     nHandles -= unregisterHandles();

                     // Now, if the number of registred handles is 0, we can
@@ -415,6 +416,9 @@
                         synchronized (lock) {
                             if (registerQueue.isEmpty()
                                     && cancelQueue.isEmpty()) {
+                                if (nbPreviousHandles > 0) {
+                                    select();
+                                }
                                 acceptor = null;
                                 break;
                             }

But I don't think it's very clean either.

Note that the problem also happen with datagram sockets and none of
the above solution seems to work in that case.

2009/2/25 Emmanuel Lecharny <elecha...@apache.org>:
> Guillaume Nodet wrote:
>>
>> I've just spotted that the acceptor is not correctly disposed.
>> I've managed to get the test running succesfully by adding the
>> following code just after server.suspend()
>>
>>        for (Listener listener :
>> server.getServerContext().getListeners().values()) {
>>            if (listener instanceof NioListener) {
>>                Field field = 
>> listener.getClass().getDeclaredField("acceptor");
>>                field.setAccessible(true);
>>                NioSocketAcceptor acceptor = (NioSocketAcceptor)
>> field.get(listener);
>>                Method method =
>> AbstractPollingIoAcceptor.class.getDeclaredMethod("dispose0");
>>                method.setAccessible(true);
>>                method.invoke(acceptor);
>>            }
>>        }
>>
>> Which is about callling the dispose0() method of the NioSocketAcceptor.
>> This method looks like:
>>
>>    protected IoFuture dispose0() throws Exception {
>>        unbind();
>>        if (!disposalFuture.isDone()) {
>>            startupAcceptor();
>>            wakeup();
>>        }
>>        return disposalFuture;
>>    }
>>
>> So I guess what we're missing is a call to:
>>            startupAcceptor();
>>            wakeup();
>> somewhere.
>> I'm not too familiar with mina internals, so I'm not sure where this
>> methods should be called or if it makes any sense to call those after
>> an unbind.
>>
>
> The problem is that when you do an acceptor.unbind(), here is what MINA does :
>
> acceptor.unbind() -->
>  unbind(getLocalAddresses()) -->
>   unbind0(localAddressesCopy) with
>
>   protected final void unbind0(List<? extends SocketAddress> localAddresses)
>           throws Exception {
>       AcceptorOperationFuture future = new AcceptorOperationFuture(
>               localAddresses);
>
>       cancelQueue.add(future);
>       startupAcceptor();
>       wakeup();
>       ...
>
> There is obviously something wrong somewhere, if you consider the following 
> test :
> org.apache.mina.transport.AbstractBindTest
>
>   public void testUnbindDisconnectsClients() throws Exception {
>       bind(true);
>       IoConnector connector = newConnector();
>       IoSession[] sessions = new IoSession[5];
>       connector.setHandler(new IoHandlerAdapter());
>
>       // Create 5 sessions, and write when established
>       for (int i = 0; i < sessions.length; i++) {
>           ConnectFuture future = connector.connect(createSocketAddress(port));
>           future.awaitUninterruptibly();
>           sessions[i] = future.getSession();
>           Assert.assertTrue(sessions[i].isConnected());
>           
> Assert.assertTrue(sessions[i].write(IoBuffer.allocate(1)).awaitUninterruptibly().isWritten());
>       }
>
>       // Wait for the server side sessions to be created.
>       Thread.sleep(500);
>
>       Collection<IoSession> managedSessions = 
> acceptor.getManagedSessions().values();
>       Assert.assertEquals(5, managedSessions.size());
>
>       // Now unbind
>       acceptor.unbind();
>
>       // Wait for the accessor to unbind
>       Thread.sleep(500);
>
>       // The session must have been closed
>       Assert.assertEquals(0, managedSessions.size());
>       for (IoSession element : managedSessions) {
>           Assert.assertFalse(element.isConnected());
>       }
>
>       // And now, try to create a session on a unbound acceptor !!!
>       ConnectFuture future = connector.connect(createSocketAddress(port));
>       future.awaitUninterruptibly();
>       IoSession session = future.getSession();
>       Assert.assertTrue(session.isConnected());
>       
> Assert.assertTrue(session.write(IoBuffer.allocate(1)).awaitUninterruptibly().isWritten());
>
>       // Wait for the server side sessions to be created.
>       Thread.sleep(500);
>
>       managedSessions = acceptor.getManagedSessions().values();
>       Assert.assertEquals(1, managedSessions.size());
>   }
>
>
> On Linux, this tests passes, all lights green !
>
> --
> --
> cordialement, regards,
> Emmanuel Lécharny
> www.iktek.com
> directory.apache.org
>
>
>



-- 
Cheers,
Guillaume Nodet
------------------------
Blog: http://gnodet.blogspot.com/
------------------------
Open Source SOA
http://fusesource.com

Reply via email to