View | Details | Raw Unified | Return to bug 54086
Collapse All | Expand All

(-)java/org/apache/catalina/tribes/transport/nio/NioReceiver.java (-12 / +41 lines)
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
    }

Return to bug 54086