Home | History | Annotate | Download | only in ch
      1 /*
      2  * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25 
     26 package sun.nio.ch;
     27 
     28 import java.nio.channels.spi.SelectorProvider;
     29 import java.security.AccessController;
     30 import sun.security.action.GetPropertyAction;
     31 
     32 /**
     33  * Creates this platform's default SelectorProvider
     34  */
     35 
     36 public class DefaultSelectorProvider {
     37 
     38     /**
     39      * Prevent instantiation.
     40      */
     41     private DefaultSelectorProvider() { }
     42 
     43     /**
     44      * Returns the default SelectorProvider.
     45      */
     46     public static SelectorProvider create() {
     47         /*
     48         The OpenJDK epoll based selector suffers from a serious bug where it
     49         can never successfully deregister keys from closed channels.
     50 
     51         The root cause of this bug is the sequence of operations that occur when
     52         a channel that's registered with a selector is closed :
     53 
     54         (0) Application code calls Channel.close().
     55 
     56         (1) The channel is "preClosed" - We dup2(2) /dev/null into the channel's
     57         file descriptor and the channel is marked as closed at the Java level.
     58 
     59         (2) All keys associated with the channel are cancelled. Cancels are
     60         lazy, which means that the Selectors involved won't necessarily
     61         deregister these keys until an ongoing call to select() (if any) returns
     62         or until the next call to select() on that selector.
     63 
     64         (3) Once all selectors associated with the channel deregister these
     65         cancelled keys, the channel FD is properly closed (via close(2)). Note
     66         that an arbitrary length of time might elapse between Step 0 and this step.
     67         This isn't a resource leak because the channel's FD is now a reference
     68         to "/dev/null".
     69 
     70         THE PROBLEM :
     71         -------------
     72         The default Selector implementation on Linux 2.6 and higher uses epoll(7).
     73         epoll can scale better than poll(2) because a lot of the state related
     74         to the interest set (the set of descriptors we're polling on) is
     75         maintained by the kernel. One of the side-effects of this design is that
     76         callers must call into the kernel to make changes to the interest set
     77         via epoll_ctl(7), for eg., by using EPOLL_CTL_ADD to add descriptors or
     78         EPOLL_CTL_DEL to remove descriptors from the interest set. A call to
     79         epoll_ctl with op = EPOLL_CTL_DEL is made when the selector attempts to
     80         deregister an FD associated with a channel from the interest set (see
     81         Step 2, above). These calls will *always fail* because the channel has
     82         been preClosed (see Step 1). They fail because the kernel uses its own
     83         internal file structure to maintain state, and rejects the command
     84         because the descriptor we're passing in describes a different file
     85         (/dev/null) that isn't selectable and isn't registered with the epoll
     86         instance.
     87 
     88         This is an issue in upstream OpenJDK as well and various select
     89         implementations (such as netty) have hacks to work around it. Outside
     90         of Android, things will work OK in most cases because the kernel has its
     91         own internal cleanup logic to deregister files from epoll instances
     92         whenever the last *non epoll* reference to the file has been closed -
     93         and usually this happens at the point at which the dup2(2) from Step 1
     94         is called. However, on Android, sockets tagged with the SocketTagger
     95         will never hit this code path because the socket tagging implementation
     96         (qtaguid) keeps a reference to the internal file until the socket
     97         has been untagged. In cases where sockets are closed without being
     98         untagged, the tagger keeps a reference to it until the process dies.
     99 
    100         THE SOLUTION :
    101         --------------
    102         We switch over to using poll(2) instead of epoll(7). One of the
    103         advantages of poll(2) is that there's less state maintained by the
    104         kernel. We don't need to make a syscall (analogous to epoll_ctl)
    105         whenever we want to remove an FD from the interest set; we merely
    106         remove it from the list of FDs passed in the next time we call
    107         through to poll. Poll is also slightly more efficient and less
    108         overhead to set up when the number of FDs being polled is small
    109         (which is the common case on Android).
    110 
    111         We also need to make sure that all tagged sockets are untagged before
    112         they're preclosed at the platform level. However, there's nothing we
    113         can do about applications that abuse public api (android.net.TrafficStats).
    114 
    115 
    116         ALTERNATE APPROACHES :
    117         ----------------------
    118         For completeness, I'm listing a couple of other approaches that were
    119         considered but discarded.
    120 
    121         - Removing preClose: This has the disadvantage of increasing the amount
    122         of time (Delta between Step 0 and Step 3) a channel's descriptor is
    123         kept alive. This also opens up races in the rare case where a
    124         closed FD number is reused on a different thread while we have reads
    125         pending.
    126 
    127         - A Synchronous call to EPOLL_CTL_DEL when a channel is removed: This is a
    128         non-starter because of the specified order of events in
    129         AbstractSelectableChannel; implCloseSelectableChannel must be called
    130         */
    131 
    132 
    133         // Android-changed: Always use PollSelectorProvider.
    134         return new sun.nio.ch.PollSelectorProvider();
    135     }
    136 
    137 }
    138