public void close() {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
            Tr.entry(this, tc, "close");
        }

        // Doing a channel.close() will actually put the keys associated with this
        // channel
        // into the associated selectors cancelledKey list, but they don't get
        // removed until the
        // next time the selector runs. In some cases, we need to make sure they are
        // really gone before we
        // we close the channel, because another thread may have requested another
        // operation
        // on the channel at the same time, which causes problems on some OS'es.
        // So, cancel them manually and wait for the selector to run once before
        // continuing

        // call super.close() to see if we are using Regular Sockets, and if so, let
        // the parent class handle closing the socket
        super.close();

        if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) {
            Tr.event(this, tc, "SocketChannel closing, local: " + socket.getLocalSocketAddress() + " remote: " + socket.getRemoteSocketAddress());
        }

        // synchronize on this SocketIOChannel to prevent duplicate closes from
        // being processed
        synchronized (this) {
            if (closed) {
                processClose = false;
            }
            closed = true;
        }

        if (processClose) {

            // checkCancel is only on if we need to manually cancel keys as
            // the socket close() is supposed to do that for us
            if (checkCancel) {
                // Remove socket from current selectors.
                if (channelSelectorRead != null) {
                    SelectionKey k = channelSelectorRead.getKey(channel);
                    if (k != null) {
                        CancelRequest cr = new CancelRequest(k);
                        synchronized (cr) {
                            channelSelectorRead.addCancelRequest(cr);
                            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                                Tr.debug(this, tc, "waiting for read key to be canceled, key is " + k);
                            }
                            try {
                                cr.wait();
                            } catch (InterruptedException e) {
                                // No FFDC code needed
                            }
                        } // end-sync
                    }
                }
                if (channelSelectorWrite != null) {
                    SelectionKey k = channelSelectorWrite.getKey(channel);
                    if (k != null) {
                        CancelRequest cr = new CancelRequest(k);
                        synchronized (cr) {
                            channelSelectorWrite.addCancelRequest(cr);
                            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                                Tr.debug(this, tc, "waiting for write key to be canceled, key is " + k);
                            }
                            try {
                                cr.wait();
                            } catch (InterruptedException e) {
                                // No FFDC code needed
                            }
                        } // end-sync
                    }
                }
            }

            try {
                if (channel != null) {
                    channel.close();
                }

                // need to make sure the keys get cancelled after the close call
                if (channelSelectorRead != null) {
                    channelSelectorRead.wakeup();
                    channelSelectorRead = null;
                }
                if (channelSelectorWrite != null) {
                    channelSelectorWrite.wakeup();
                    channelSelectorWrite = null;
                }

            } catch (Throwable t) {
                if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                    Tr.debug(this, tc, "Error closing channel: " + t);
                }
                // ignore all shutdown/close errors
            }
        }
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
            Tr.exit(this, tc, "close");
        }
    }
public void close ( ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEntryEnabled ( ) ) { Tr . entry ( this , tc , "close" ) ; } super . close ( ) ; if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEventEnabled ( ) ) { Tr . event ( this , tc , "SocketChannel closing, local: " + socket . getLocalSocketAddress ( ) + " remote: " + socket . getRemoteSocketAddress ( ) ) ; } synchronized ( this ) { if ( closed ) { processClose = false ; } closed = true ; } if ( processClose ) { if ( checkCancel ) { if ( channelSelectorRead != null ) { SelectionKey k = channelSelectorRead . getKey ( channel ) ; if ( k != null ) { CancelRequest cr = new CancelRequest ( k ) ; synchronized ( cr ) { channelSelectorRead . addCancelRequest ( cr ) ; if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) { Tr . debug ( this , tc , "waiting for read key to be canceled, key is " + k ) ; } try { cr . wait ( ) ; } catch ( InterruptedException e ) { } } } } if ( channelSelectorWrite != null ) { SelectionKey k = channelSelectorWrite . getKey ( channel ) ; if ( k != null ) { CancelRequest cr = new CancelRequest ( k ) ; synchronized ( cr ) { channelSelectorWrite . addCancelRequest ( cr ) ; if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) { Tr . debug ( this , tc , "waiting for write key to be canceled, key is " + k ) ; } try { cr . wait ( ) ; } catch ( InterruptedException e ) { } } } } } try { if ( channel != null ) { channel . close ( ) ; } if ( channelSelectorRead != null ) { channelSelectorRead . wakeup ( ) ; channelSelectorRead = null ; } if ( channelSelectorWrite != null ) { channelSelectorWrite . wakeup ( ) ; channelSelectorWrite = null ; } } catch ( Throwable t ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) { Tr . debug ( this , tc , "Error closing channel: " + t ) ; } } } if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEntryEnabled ( ) ) { Tr . exit ( this , tc , "close" ) ; } }
Close the socket