Lines 27-32
Link Here
|
27 |
import java.nio.channels.Selector; |
27 |
import java.nio.channels.Selector; |
28 |
import java.nio.channels.ServerSocketChannel; |
28 |
import java.nio.channels.ServerSocketChannel; |
29 |
import java.nio.channels.SocketChannel; |
29 |
import java.nio.channels.SocketChannel; |
|
|
30 |
import java.util.ConcurrentModificationException; |
30 |
import java.util.Iterator; |
31 |
import java.util.Iterator; |
31 |
import java.util.LinkedList; |
32 |
import java.util.LinkedList; |
32 |
import java.util.Set; |
33 |
import java.util.Set; |
Lines 378-395
Link Here
|
378 |
Selector selector = this.selector.getAndSet(null); |
379 |
Selector selector = this.selector.getAndSet(null); |
379 |
if (selector==null) return; |
380 |
if (selector==null) return; |
380 |
try { |
381 |
try { |
381 |
Iterator<SelectionKey> it = selector.keys().iterator(); |
382 |
int closeAttempt = 1; |
382 |
// look at each key in the selected set |
383 |
int maxCloseAttempts = 3; |
383 |
while (it.hasNext()) { |
384 |
boolean goodClose = false; |
384 |
SelectionKey key = it.next(); |
385 |
do { |
385 |
key.channel().close(); |
386 |
try { |
386 |
key.attach(null); |
387 |
// attempt to close known keys/channels |
387 |
key.cancel(); |
388 |
Iterator<SelectionKey> it = selector.keys().iterator(); |
388 |
} |
389 |
|
389 |
}catch ( IOException ignore ){ |
390 |
// in order to see a ConcurrentModificationException thrown |
390 |
if (log.isWarnEnabled()) { |
391 |
// it is helpful to sleep after obtaining the key set iterator |
391 |
log.warn("Unable to cleanup on selector close.",ignore); |
392 |
//try { |
392 |
} |
393 |
// System.err.println("sleeping..."); |
|
|
394 |
// Thread.sleep(2000); |
395 |
//} catch (InterruptedException ignore) {} |
396 |
|
397 |
while (it.hasNext()) { |
398 |
SelectionKey key = it.next(); |
399 |
try { |
400 |
key.channel().close(); |
401 |
} catch (IOException ignore) { |
402 |
if (log.isWarnEnabled()) { |
403 |
log.warn("Unable to cleanup on selector close.",ignore); |
404 |
} |
405 |
} |
406 |
key.attach(null); |
407 |
key.cancel(); |
408 |
} |
409 |
goodClose = true; |
410 |
} catch (ConcurrentModificationException concurrentException) { |
411 |
// This will occur when another thread is processing closed |
412 |
// connections because when connections are closed, the |
413 |
// associated channel is closed and the key is canceled. |
414 |
// See concurrency notes for Selector. |
415 |
if (log.isDebugEnabled()) { |
416 |
log.debug("Caught exception during close attempt " + closeAttempt + " of " + |
417 |
maxCloseAttempts + ". Retrying.", concurrentException); |
418 |
} |
419 |
try { Thread.sleep(100 * closeAttempt); } catch(InterruptedException ignore) {} |
420 |
} |
421 |
} while (!goodClose && closeAttempt++ < maxCloseAttempts); |
393 |
}catch ( ClosedSelectorException ignore){} |
422 |
}catch ( ClosedSelectorException ignore){} |
394 |
selector.close(); |
423 |
selector.close(); |
395 |
} |
424 |
} |