1027N/A/*
3261N/A * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
1027N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1027N/A *
1027N/A * This code is free software; you can redistribute it and/or modify it
1027N/A * under the terms of the GNU General Public License version 2 only, as
1027N/A * published by the Free Software Foundation.
1027N/A *
1027N/A * This code is distributed in the hope that it will be useful, but WITHOUT
1027N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1027N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1027N/A * version 2 for more details (a copy is included in the LICENSE file that
1027N/A * accompanied this code).
1027N/A *
1027N/A * You should have received a copy of the GNU General Public License version
1027N/A * 2 along with this work; if not, write to the Free Software Foundation,
1027N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1027N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
1027N/A */
1027N/A
1027N/A/* @test
1027N/A * @bug 6693490
1027N/A * @summary Pre-close file descriptor may inadvertently get registered with
1027N/A * epoll during close
1027N/A */
1027N/A
1027N/Aimport java.net.*;
1027N/Aimport java.nio.channels.*;
1027N/Aimport java.util.concurrent.*;
1027N/Aimport java.util.*;
1027N/Aimport java.io.IOException;
1027N/A
1027N/Apublic class RegAfterPreClose {
1027N/A
2546N/A static final int TEST_ITERATIONS = 300;
1027N/A static volatile boolean done;
1027N/A
1027N/A /**
1027N/A * A task that continuously connects to a given address and immediately
1027N/A * closes the connection.
1027N/A */
1027N/A static class Connector implements Runnable {
1027N/A private final SocketAddress sa;
1027N/A Connector(int port) throws IOException {
1027N/A InetAddress lh = InetAddress.getLocalHost();
1027N/A this.sa = new InetSocketAddress(lh, port);
1027N/A }
1027N/A public void run() {
1027N/A while (!done) {
1027N/A try {
1027N/A SocketChannel.open(sa).close();
1027N/A } catch (IOException x) {
1027N/A // back-off as probably resource related
1027N/A try {
1027N/A Thread.sleep(10);
1027N/A } catch (InterruptedException ignore) { }
1027N/A }
1027N/A }
1027N/A }
1027N/A }
1027N/A
1027N/A /**
1027N/A * A task that closes a channel.
1027N/A */
1027N/A static class Closer implements Runnable {
1027N/A private final Channel channel;
1027N/A Closer(Channel sc) {
1027N/A this.channel = sc;
1027N/A }
1027N/A public void run() {
1027N/A try {
1027N/A channel.close();
1027N/A } catch (IOException ignore) { }
1027N/A }
1027N/A }
1027N/A
1027N/A public static void main(String[] args) throws Exception {
1027N/A // create listener
1027N/A InetSocketAddress isa = new InetSocketAddress(0);
1027N/A ServerSocketChannel ssc = ServerSocketChannel.open();
1027N/A ssc.socket().bind(isa);
1027N/A
1027N/A // register with Selector
1027N/A final Selector sel = Selector.open();
1027N/A ssc.configureBlocking(false);
1027N/A SelectionKey key = ssc.register(sel, SelectionKey.OP_ACCEPT);
1027N/A
1027N/A ThreadFactory factory = new ThreadFactory() {
1027N/A @Override
1027N/A public Thread newThread(Runnable r) {
1027N/A Thread t = new Thread(r);
1027N/A t.setDaemon(true);
1027N/A return t;
1027N/A }
1027N/A };
1027N/A
1027N/A // create Executor that handles tasks that closes channels
1027N/A // "asynchronously" - this creates the conditions to provoke the bug.
2546N/A ExecutorService executor = Executors.newFixedThreadPool(2, factory);
1027N/A
1027N/A // submit task that connects to listener
1027N/A executor.execute(new Connector(ssc.socket().getLocalPort()));
1027N/A
1027N/A // loop accepting connections until done (or an IOException is thrown)
2546N/A int remaining = TEST_ITERATIONS;
2546N/A while (remaining > 0) {
1027N/A sel.select();
1027N/A if (key.isAcceptable()) {
1027N/A SocketChannel sc = ssc.accept();
1027N/A if (sc != null) {
2546N/A remaining--;
1027N/A sc.configureBlocking(false);
1027N/A sc.register(sel, SelectionKey.OP_READ);
1027N/A executor.execute(new Closer(sc));
1027N/A }
1027N/A }
1027N/A sel.selectedKeys().clear();
1027N/A }
2546N/A done = true;
2546N/A sel.close();
2546N/A executor.shutdown();
1027N/A }
1027N/A}