/** * Closes the channel. * * @param diagnosis If someone (either this side or the other side) tries to use a channel that's * already closed, they'll get a stack trace indicating that the channel has already been * closed. This diagnosis, if provided, will further chained to that exception, providing more * contextual information about why the channel was closed. * @since 2.8 */ public synchronized void close(Throwable diagnosis) throws IOException { if (outClosed != null) return; // already closed send(new CloseCommand(this, diagnosis)); outClosed = new IOException() .initCause( diagnosis); // last command sent. no further command allowed. lock guarantees that // no command will slip inbetween try { transport.closeWrite(); } catch (IOException e) { // there's a race condition here. // the remote peer might have already responded to the close command // and closed the connection, in which case our close invocation // could fail with errors like // "java.io.IOException: The pipe is being closed" // so let's ignore this error. } // termination is done by CloseCommand when we received it. }