0

I have an issue where a server(Apache Synapse) intermittently throws "java.nio.channels.ClosedChannelException".

java.nio.channels.ClosedChannelException
at sun.nio.ch.SocketChannelImpl.ensureWriteOpen(SocketChannelImpl.java:135)
at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:326)
at org.apache.http.impl.nio.reactor.SessionOutputBufferImpl.flush(SessionOutputBufferImpl.java:167)
at org.apache.http.impl.nio.DefaultNHttpServerConnection.produceOutput(DefaultNHttpServerConnection.java:323)
at org.apache.synapse.transport.http.conn.LoggingNHttpServerConnection.produceOutput(LoggingNHttpServerConnection.java:112)
at org.apache.synapse.transport.passthru.ServerIODispatch.onOutputReady(ServerIODispatch.java:87)
at org.apache.synapse.transport.passthru.ServerIODispatch.onOutputReady(ServerIODispatch.java:39)
at org.apache.http.impl.nio.reactor.AbstractIODispatch.outputReady(AbstractIODispatch.java:143)
at org.apache.http.impl.nio.reactor.BaseIOReactor.writable(BaseIOReactor.java:180)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:342)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:316)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:277)
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:105)
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:584)
at java.lang.Thread.run(Thread.java:662)

Apparently the server tries to do some IO operation on an already closed channel. I want to write a client program to reproduce the issue at will. The client deliberately closes the channel resulting the server to throw the Exception. This is the code for the client.

public class Client
{
    String hostIp;
    int hostPort;

    public Client(String hostIp, int hostPort) {
        this.hostIp = hostIp;
        this.hostPort = hostPort;
    }

    public void runClient() throws IOException {
        Socket clientSocket = null;
        PrintWriter out = null;
        BufferedReader in = null;

        try {
            clientSocket = new Socket(hostIp, hostPort);
            out = new PrintWriter(clientSocket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        } catch (UnknownHostException e) {
            System.err.println("Unknown host: " + hostIp);
            System.exit(1);
        } catch (IOException e) {
            System.err.println("Couldn't connect to: " + hostIp);
            System.exit(1);
        }

        String getMessage = "GET /services/echo?wsdl2 HTTP/1.1\n" +
                "Host:localhost\n";

        System.out.println("Client connected to host : " + hostIp + " port: " + hostPort);

        out.println(getMessage);

        in.close();
        out.close();
        clientSocket.close();
    }

    public static void main(String[] args) throws IOException {

        Client client = new Client("localhost", 8280);
        client.runClient();
    }
}

When the client is run, the server just throws an IOException informing that the pipe is broken.

java.io.IOException: Broken pipe
    at sun.nio.ch.FileDispatcher.write0(Native Method)
    at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:29)
    at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:69)
    at sun.nio.ch.IOUtil.write(IOUtil.java:40)
    at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:336)
    at org.apache.http.impl.nio.reactor.SessionOutputBufferImpl.flush(SessionOutputBufferImpl.java:100)
    at org.apache.http.impl.nio.DefaultNHttpServerConnection.produceOutput(DefaultNHttpServerConnection.java:220)
    at org.apache.synapse.transport.http.conn.LoggingNHttpServerConnection.produceOutput(LoggingNHttpServerConnection.java:112)
    at org.apache.synapse.transport.passthru.ServerIODispatch.onOutputReady(ServerIODispatch.java:87)
    at org.apache.synapse.transport.passthru.ServerIODispatch.onOutputReady(ServerIODispatch.java:39)
    at org.apache.http.impl.nio.reactor.AbstractIODispatch.outputReady(AbstractIODispatch.java:141)
    at org.apache.http.impl.nio.reactor.BaseIOReactor.writable(BaseIOReactor.java:181)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:346)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:320)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:280)
    at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:106)
    at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:604)
    at java.lang.Thread.run(Thread.java:662)

What should I do from the client side to make the server throw a "ClosedChannelException" ?

Jeewantha
  • 965
  • 1
  • 11
  • 28

1 Answers1

0

How to close a socket channel from client side so that the server throws java.nio.channels.ClosedChannelException

You can't.

What should I do from the client side to make the server throw a "ClosedChannelException" ?

Nothing.

You have a basic misunderstanding of ClosedChannelException. It is thrown when you have closed your local Channel and have kept using it. Not when the connection has been closed by the peer.

If you are looking for an end-of-stream indication, use the case where read() returns -1.

If you are looking for an indication of a dropped or failed connection, use the case where write() throws IOException: connection reset.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • I think you misunderstood my question. Its true that ClosedChannelException is thrown when you try to use an already closed Channel. Synapse already does that, thats why its throwing the exception. My question was "how do I reproduce this issue programatically?". I want to mimic this situation in my local setup so that I can debug and fix it. Thanks – Jeewantha Aug 19 '13 at 16:30
  • No, your question was 'how to close a socket channel from the client side so that the server throws a ClosedChannelException?'. It's up there in black and white, and I've answered it. You have a bug in your server. What you need is a breakpoint on SocketChannel.close(), not magical non-existent programming at the client. Possibly the client has *already* closed its end, so that the server has read EOS and then done the same, and then continued on buggily. Or else the server has closed prematurely. You're going to have to solve this at the server end. Not the client. – user207421 Aug 19 '13 at 22:54