0

The following test program does a simple bind/accept and then shuts down the channel group.

I would expect the program to print out the resulting ShutdownChannelGroupException, but instead it never calls the completion handler and throws the exception on the thread pool.

Can someone shed some light on whats going on? Am I misinterpreting the docs when they say shutdownNow() has the following behavior: "The group terminates when all actively executing completion handlers have run to completion and all resources have been released".

Is it that the callback isn't 'active' yet and therefore just gets discarded?

public static void main(String[] args) throws java.io.IOException, InterruptedException {

    ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    AsynchronousChannelGroup group = AsynchronousChannelGroup.withThreadPool(service);
    AsynchronousServerSocketChannel acceptor = AsynchronousServerSocketChannel.open(group);
    acceptor.bind(new InetSocketAddress(50000));
    acceptor.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() {
        @Override
        public void completed(AsynchronousSocketChannel result, Object attachment) {

        }

        @Override
        public void failed(Throwable exc, Object attachment) {
            System.out.println("failed: " + exc.getMessage());
        }
    });
    System.out.println("Shutting down");
    group.shutdownNow();
    System.out.println("Awaiting termination");
    group.awaitTermination(60, TimeUnit.SECONDS);
    System.out.println("Sleeping");
    Thread.sleep(1000);

}
jadamcrain
  • 125
  • 7

2 Answers2

0

"actively executing completion handlers" means just that, handlers that are executing methods "completed" or "failed".

Then, doc for AsynchronousServerSocketChannel.accept() reads:

"the group is shutdown and a connection is accepted, then the connection is closed, and the operation completes with an IOException".

So when connection is not accepted, no reaction is supposed. Just like you, I would expect that when the group is shutdown, not yet accepted connection handler should call "failed()", but we do not know all the considerations behind the current implementation.

Alexei Kaigorodov
  • 13,189
  • 1
  • 21
  • 38
  • Thanks, Alexei. The same behavior occurs for asynchronous read operations. I.E. if you have pending reads, and you shutdown the channel group they blow up on the thread pool without calling the handler. IMO, this really limits the usefulness of the shutdown() methods on AsynchronousChannelGroup. In order to get a clean shutdown now, I have to track open connections in a thread-safe datastucture as a work around. – jadamcrain Dec 29 '12 at 16:56
0

I have seen this behavior as well, but only on Windows, the same code had no problems on Centos/Ubuntu in my experience. I think your assumption is correct, something in the IOCP processing is not exiting clean during shutdownNow(). I have found that if one or more connections are live, the shutdownNow() will complete cleanly. Of course this could vary with JVMs.

Something like this worked for me (open a connection and do not close it):

idle = AsynchronousSocketChannel.open(group);
Future<Void> fut = idle.connect(new InetSocketAddress("localhost",50000));
fut.get();

This is most certainly a hack but may help you ignore nuisance exceptions so that you can focus on the real ones.

codeSF
  • 1,162
  • 9
  • 16