1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.mina.core.service;
22
23 import static org.junit.Assert.fail;
24
25 import org.apache.mina.core.future.CloseFuture;
26 import org.apache.mina.core.future.ConnectFuture;
27 import org.apache.mina.core.session.IdleStatus;
28 import org.apache.mina.core.session.IoSession;
29 import org.apache.mina.filter.codec.ProtocolCodecFilter;
30 import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
31 import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
32 import org.apache.mina.transport.socket.nio.NioSocketConnector;
33 import org.apache.mina.util.AvailablePortFinder;
34 import org.junit.Ignore;
35 import org.junit.Test;
36
37 import java.io.IOException;
38 import java.net.InetSocketAddress;
39 import java.nio.charset.Charset;
40 import java.nio.charset.StandardCharsets;
41 import java.util.concurrent.CountDownLatch;
42
43
44
45
46
47
48 public class AbstractIoServiceDIRMINA1076Test {
49
50 @Test( timeout = 15000 )
51 @Ignore
52 public void testDispose()
53 throws Exception {
54
55 long startTime = System.currentTimeMillis();
56
57 while ( System.currentTimeMillis() < startTime + 10000 ) {
58 final CountDownLatch disposalLatch = new CountDownLatch( 1 );
59 Thread thread = new Thread() {
60
61 public void run() {
62
63 final IoAcceptor acceptor = new NioSocketAcceptor();
64 acceptor.getFilterChain()
65 .addLast( "codec",
66 new ProtocolCodecFilter( new TextLineCodecFactory( StandardCharsets.UTF_8 ) ) );
67
68 acceptor.setHandler( new ServerHandler() );
69
70 acceptor.getSessionConfig().setReadBufferSize( 2048 );
71 acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );
72 int nextAvailable = AvailablePortFinder.getNextAvailable();
73 try {
74 acceptor.bind( new InetSocketAddress( nextAvailable ) );
75 } catch ( IOException e1 ) {
76 throw new RuntimeException( e1 );
77 }
78
79 final NioSocketConnector connector = new NioSocketConnector();
80
81
82 connector.setConnectTimeoutMillis( 30 * 1000L );
83
84 connector.setHandler( new ClientHandler() );
85 connector.getFilterChain()
86 .addLast( "codec",
87 new ProtocolCodecFilter( new TextLineCodecFactory( StandardCharsets.UTF_8 ) ) );
88
89
90 ConnectFuture cf = connector.connect( new InetSocketAddress( "localhost", nextAvailable ) );
91 cf.awaitUninterruptibly();
92
93 IoSession session = cf.getSession();
94
95
96 session.write( "Hello World!\r" );
97
98
99 CountDownLatch latch = (CountDownLatch)session.getAttribute( "latch" );
100 try {
101 latch.await();
102 } catch ( InterruptedException e1 ) {
103 Thread.currentThread().interrupt();
104 }
105
106
107 CloseFuture closeFuture = session.closeOnFlush();
108
109 connector.dispose( true );
110
111 closeFuture.awaitUninterruptibly();
112 acceptor.unbind();
113 acceptor.dispose( true );
114 disposalLatch.countDown();
115 }
116 };
117 thread.setDaemon( true );
118 thread.start();
119 disposalLatch.await();
120 thread.join( 1000 );
121
122 if ( thread.isAlive() ) {
123 for ( StackTraceElement stackTraceElement : thread.getStackTrace() ) {
124 if ( "dispose".equals( stackTraceElement.getMethodName() )
125 && AbstractIoService.class.getCanonicalName().equals( stackTraceElement.getClassName() ) ) {
126 System.err.println( "Detected hang in AbstractIoService.dispose()!" );
127 }
128 }
129 fail( "Thread should have died by now, supposed hang in AbstractIoService.dispose()" );
130 }
131 }
132 ;
133 }
134
135 public static class ClientHandler
136 extends
137 IoHandlerAdapter {
138
139 @Override
140 public void sessionCreated( IoSession session )
141 throws Exception {
142 session.setAttribute( "latch", new CountDownLatch( 1 ) );
143 }
144
145
146
147 @Override
148 public void messageReceived( IoSession session, Object message )
149 throws Exception {
150 CountDownLatch latch = (CountDownLatch)session.getAttribute( "latch" );
151 latch.countDown();
152 }
153
154
155
156 @Override
157 public void exceptionCaught( IoSession session, Throwable cause )
158 throws Exception {}
159 }
160
161 public static class ServerHandler
162 extends
163 IoHandlerAdapter {
164
165 @Override
166 public void messageReceived( IoSession session, Object message )
167 throws Exception {
168 session.write( message.toString() );
169 }
170
171
172
173 @Override
174 public void exceptionCaught( IoSession session, Throwable cause )
175 throws Exception {}
176
177 }
178
179 }