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 // Android-removed: Dead code: We always use PollSelectorProvider. 44 /* 45 @SuppressWarnings("unchecked") 46 private static SelectorProvider createProvider(String cn) { 47 Class<SelectorProvider> c; 48 try { 49 c = (Class<SelectorProvider>)Class.forName(cn); 50 } catch (ClassNotFoundException x) { 51 throw new AssertionError(x); 52 } 53 try { 54 return c.newInstance(); 55 } catch (IllegalAccessException | InstantiationException x) { 56 throw new AssertionError(x); 57 } 58 59 } 60 */ 61 62 /** 63 * Returns the default SelectorProvider. 64 */ 65 public static SelectorProvider create() { 66 // Android-note: Explain why we always use of PollSelectorProvider. 67 /* 68 The OpenJDK epoll based selector suffers from a serious bug where it 69 can never successfully deregister keys from closed channels. 70 71 The root cause of this bug is the sequence of operations that occur when 72 a channel that's registered with a selector is closed : 73 74 (0) Application code calls Channel.close(). 75 76 (1) The channel is "preClosed" - We dup2(2) /dev/null into the channel's 77 file descriptor and the channel is marked as closed at the Java level. 78 79 (2) All keys associated with the channel are cancelled. Cancels are 80 lazy, which means that the Selectors involved won't necessarily 81 deregister these keys until an ongoing call to select() (if any) returns 82 or until the next call to select() on that selector. 83 84 (3) Once all selectors associated with the channel deregister these 85 cancelled keys, the channel FD is properly closed (via close(2)). Note 86 that an arbitrary length of time might elapse between Step 0 and this step. 87 This isn't a resource leak because the channel's FD is now a reference 88 to "/dev/null". 89 90 THE PROBLEM : 91 ------------- 92 The default Selector implementation on Linux 2.6 and higher uses epoll(7). 93 epoll can scale better than poll(2) because a lot of the state related 94 to the interest set (the set of descriptors we're polling on) is 95 maintained by the kernel. One of the side-effects of this design is that 96 callers must call into the kernel to make changes to the interest set 97 via epoll_ctl(7), for eg., by using EPOLL_CTL_ADD to add descriptors or 98 EPOLL_CTL_DEL to remove descriptors from the interest set. A call to 99 epoll_ctl with op = EPOLL_CTL_DEL is made when the selector attempts to 100 deregister an FD associated with a channel from the interest set (see 101 Step 2, above). These calls will *always fail* because the channel has 102 been preClosed (see Step 1). They fail because the kernel uses its own 103 internal file structure to maintain state, and rejects the command 104 because the descriptor we're passing in describes a different file 105 (/dev/null) that isn't selectable and isn't registered with the epoll 106 instance. 107 108 This is an issue in upstream OpenJDK as well and various select 109 implementations (such as netty) have hacks to work around it. Outside 110 of Android, things will work OK in most cases because the kernel has its 111 own internal cleanup logic to deregister files from epoll instances 112 whenever the last *non epoll* reference to the file has been closed - 113 and usually this happens at the point at which the dup2(2) from Step 1 114 is called. However, on Android, sockets tagged with the SocketTagger 115 will never hit this code path because the socket tagging implementation 116 (qtaguid) keeps a reference to the internal file until the socket 117 has been untagged. In cases where sockets are closed without being 118 untagged, the tagger keeps a reference to it until the process dies. 119 120 THE SOLUTION : 121 -------------- 122 We switch over to using poll(2) instead of epoll(7). One of the 123 advantages of poll(2) is that there's less state maintained by the 124 kernel. We don't need to make a syscall (analogous to epoll_ctl) 125 whenever we want to remove an FD from the interest set; we merely 126 remove it from the list of FDs passed in the next time we call 127 through to poll. Poll is also slightly more efficient and less 128 overhead to set up when the number of FDs being polled is small 129 (which is the common case on Android). 130 131 We also need to make sure that all tagged sockets are untagged before 132 they're preclosed at the platform level. However, there's nothing we 133 can do about applications that abuse public api (android.net.TrafficStats). 134 135 136 ALTERNATE APPROACHES : 137 ---------------------- 138 For completeness, I'm listing a couple of other approaches that were 139 considered but discarded. 140 141 - Removing preClose: This has the disadvantage of increasing the amount 142 of time (Delta between Step 0 and Step 3) a channel's descriptor is 143 kept alive. This also opens up races in the rare case where a 144 closed FD number is reused on a different thread while we have reads 145 pending. 146 147 - A Synchronous call to EPOLL_CTL_DEL when a channel is removed: This is a 148 non-starter because of the specified order of events in 149 AbstractSelectableChannel; implCloseSelectableChannel must be called 150 */ 151 152 153 // Android-changed: Always use PollSelectorProvider. 154 /* 155 String osname = AccessController 156 .doPrivileged(new GetPropertyAction("os.name")); 157 if (osname.equals("SunOS")) 158 return createProvider("sun.nio.ch.DevPollSelectorProvider"); 159 if (osname.equals("Linux")) 160 return createProvider("sun.nio.ch.EPollSelectorProvider"); 161 */ 162 return new sun.nio.ch.PollSelectorProvider(); 163 } 164 165 } 166