Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java
32288 views
1
/*
2
* Copyright (c) 2008, 2013, 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.*;
29
import java.util.concurrent.*;
30
import java.io.IOException;
31
import java.io.FileDescriptor;
32
import java.net.InetSocketAddress;
33
import java.util.concurrent.atomic.AtomicBoolean;
34
import java.security.AccessControlContext;
35
import java.security.AccessController;
36
import java.security.PrivilegedAction;
37
38
/**
39
* Unix implementation of AsynchronousServerSocketChannel
40
*/
41
42
class UnixAsynchronousServerSocketChannelImpl
43
extends AsynchronousServerSocketChannelImpl
44
implements Port.PollableChannel
45
{
46
private final static NativeDispatcher nd = new SocketDispatcher();
47
48
private final Port port;
49
private final int fdVal;
50
51
// flag to indicate an accept is outstanding
52
private final AtomicBoolean accepting = new AtomicBoolean();
53
private void enableAccept() {
54
accepting.set(false);
55
}
56
57
// used to ensure that the context for an asynchronous accept is visible
58
// the pooled thread that handles the I/O event
59
private final Object updateLock = new Object();
60
61
// pending accept
62
private boolean acceptPending;
63
private CompletionHandler<AsynchronousSocketChannel,Object> acceptHandler;
64
private Object acceptAttachment;
65
private PendingFuture<AsynchronousSocketChannel,Object> acceptFuture;
66
67
// context for permission check when security manager set
68
private AccessControlContext acceptAcc;
69
70
71
UnixAsynchronousServerSocketChannelImpl(Port port)
72
throws IOException
73
{
74
super(port);
75
76
try {
77
IOUtil.configureBlocking(fd, false);
78
} catch (IOException x) {
79
nd.close(fd); // prevent leak
80
throw x;
81
}
82
this.port = port;
83
this.fdVal = IOUtil.fdVal(fd);
84
85
// add mapping from file descriptor to this channel
86
port.register(fdVal, this);
87
}
88
89
@Override
90
void implClose() throws IOException {
91
// remove the mapping
92
port.unregister(fdVal);
93
94
// close file descriptor
95
nd.close(fd);
96
97
// if there is a pending accept then complete it
98
CompletionHandler<AsynchronousSocketChannel,Object> handler;
99
Object att;
100
PendingFuture<AsynchronousSocketChannel,Object> future;
101
synchronized (updateLock) {
102
if (!acceptPending)
103
return; // no pending accept
104
acceptPending = false;
105
handler = acceptHandler;
106
att = acceptAttachment;
107
future = acceptFuture;
108
}
109
110
// discard the stack trace as otherwise it may appear that implClose
111
// has thrown the exception.
112
AsynchronousCloseException x = new AsynchronousCloseException();
113
x.setStackTrace(new StackTraceElement[0]);
114
if (handler == null) {
115
future.setFailure(x);
116
} else {
117
// invoke by submitting task rather than directly
118
Invoker.invokeIndirectly(this, handler, att, null, x);
119
}
120
}
121
122
@Override
123
public AsynchronousChannelGroupImpl group() {
124
return port;
125
}
126
127
/**
128
* Invoked by event handling thread when listener socket is polled
129
*/
130
@Override
131
public void onEvent(int events, boolean mayInvokeDirect) {
132
synchronized (updateLock) {
133
if (!acceptPending)
134
return; // may have been grabbed by asynchronous close
135
acceptPending = false;
136
}
137
138
// attempt to accept connection
139
FileDescriptor newfd = new FileDescriptor();
140
InetSocketAddress[] isaa = new InetSocketAddress[1];
141
Throwable exc = null;
142
try {
143
begin();
144
int n = accept(this.fd, newfd, isaa);
145
146
// spurious wakeup, is this possible?
147
if (n == IOStatus.UNAVAILABLE) {
148
synchronized (updateLock) {
149
acceptPending = true;
150
}
151
port.startPoll(fdVal, Net.POLLIN);
152
return;
153
}
154
155
} catch (Throwable x) {
156
if (x instanceof ClosedChannelException)
157
x = new AsynchronousCloseException();
158
exc = x;
159
} finally {
160
end();
161
}
162
163
// Connection accepted so finish it when not holding locks.
164
AsynchronousSocketChannel child = null;
165
if (exc == null) {
166
try {
167
child = finishAccept(newfd, isaa[0], acceptAcc);
168
} catch (Throwable x) {
169
if (!(x instanceof IOException) && !(x instanceof SecurityException))
170
x = new IOException(x);
171
exc = x;
172
}
173
}
174
175
// copy field befores accept is re-renabled
176
CompletionHandler<AsynchronousSocketChannel,Object> handler = acceptHandler;
177
Object att = acceptAttachment;
178
PendingFuture<AsynchronousSocketChannel,Object> future = acceptFuture;
179
180
// re-enable accepting and invoke handler
181
enableAccept();
182
183
if (handler == null) {
184
future.setResult(child, exc);
185
// if an async cancel has already cancelled the operation then
186
// close the new channel so as to free resources
187
if (child != null && future.isCancelled()) {
188
try {
189
child.close();
190
} catch (IOException ignore) { }
191
}
192
} else {
193
Invoker.invoke(this, handler, att, child, exc);
194
}
195
}
196
197
/**
198
* Completes the accept by creating the AsynchronousSocketChannel for
199
* the given file descriptor and remote address. If this method completes
200
* with an IOException or SecurityException then the channel/file descriptor
201
* will be closed.
202
*/
203
private AsynchronousSocketChannel finishAccept(FileDescriptor newfd,
204
final InetSocketAddress remote,
205
AccessControlContext acc)
206
throws IOException, SecurityException
207
{
208
AsynchronousSocketChannel ch = null;
209
try {
210
ch = new UnixAsynchronousSocketChannelImpl(port, newfd, remote);
211
} catch (IOException x) {
212
nd.close(newfd);
213
throw x;
214
}
215
216
// permission check must always be in initiator's context
217
try {
218
if (acc != null) {
219
AccessController.doPrivileged(new PrivilegedAction<Void>() {
220
public Void run() {
221
SecurityManager sm = System.getSecurityManager();
222
if (sm != null) {
223
sm.checkAccept(remote.getAddress().getHostAddress(),
224
remote.getPort());
225
}
226
return null;
227
}
228
}, acc);
229
} else {
230
SecurityManager sm = System.getSecurityManager();
231
if (sm != null) {
232
sm.checkAccept(remote.getAddress().getHostAddress(),
233
remote.getPort());
234
}
235
}
236
} catch (SecurityException x) {
237
try {
238
ch.close();
239
} catch (Throwable suppressed) {
240
x.addSuppressed(suppressed);
241
}
242
throw x;
243
}
244
return ch;
245
}
246
247
@Override
248
Future<AsynchronousSocketChannel> implAccept(Object att,
249
CompletionHandler<AsynchronousSocketChannel,Object> handler)
250
{
251
// complete immediately if channel is closed
252
if (!isOpen()) {
253
Throwable e = new ClosedChannelException();
254
if (handler == null) {
255
return CompletedFuture.withFailure(e);
256
} else {
257
Invoker.invoke(this, handler, att, null, e);
258
return null;
259
}
260
}
261
if (localAddress == null)
262
throw new NotYetBoundException();
263
264
// cancel was invoked with pending accept so connection may have been
265
// dropped.
266
if (isAcceptKilled())
267
throw new RuntimeException("Accept not allowed due cancellation");
268
269
// check and set flag to prevent concurrent accepting
270
if (!accepting.compareAndSet(false, true))
271
throw new AcceptPendingException();
272
273
// attempt accept
274
FileDescriptor newfd = new FileDescriptor();
275
InetSocketAddress[] isaa = new InetSocketAddress[1];
276
Throwable exc = null;
277
try {
278
begin();
279
280
int n = accept(this.fd, newfd, isaa);
281
if (n == IOStatus.UNAVAILABLE) {
282
283
// need calling context when there is security manager as
284
// permission check may be done in a different thread without
285
// any application call frames on the stack
286
PendingFuture<AsynchronousSocketChannel,Object> result = null;
287
synchronized (updateLock) {
288
if (handler == null) {
289
this.acceptHandler = null;
290
result = new PendingFuture<AsynchronousSocketChannel,Object>(this);
291
this.acceptFuture = result;
292
} else {
293
this.acceptHandler = handler;
294
this.acceptAttachment = att;
295
}
296
this.acceptAcc = (System.getSecurityManager() == null) ?
297
null : AccessController.getContext();
298
this.acceptPending = true;
299
}
300
301
// register for connections
302
port.startPoll(fdVal, Net.POLLIN);
303
return result;
304
}
305
} catch (Throwable x) {
306
// accept failed
307
if (x instanceof ClosedChannelException)
308
x = new AsynchronousCloseException();
309
exc = x;
310
} finally {
311
end();
312
}
313
314
AsynchronousSocketChannel child = null;
315
if (exc == null) {
316
// connection accepted immediately
317
try {
318
child = finishAccept(newfd, isaa[0], null);
319
} catch (Throwable x) {
320
exc = x;
321
}
322
}
323
324
// re-enable accepting before invoking handler
325
enableAccept();
326
327
if (handler == null) {
328
return CompletedFuture.withResult(child, exc);
329
} else {
330
Invoker.invokeIndirectly(this, handler, att, child, exc);
331
return null;
332
}
333
}
334
335
/**
336
* Accept a connection on a socket.
337
*
338
* @implNote Wrap native call to allow instrumentation.
339
*/
340
private int accept(FileDescriptor ssfd, FileDescriptor newfd,
341
InetSocketAddress[] isaa)
342
throws IOException
343
{
344
return accept0(ssfd, newfd, isaa);
345
}
346
347
// -- Native methods --
348
349
private static native void initIDs();
350
351
// Accepts a new connection, setting the given file descriptor to refer to
352
// the new socket and setting isaa[0] to the socket's remote address.
353
// Returns 1 on success, or IOStatus.UNAVAILABLE.
354
//
355
private native int accept0(FileDescriptor ssfd, FileDescriptor newfd,
356
InetSocketAddress[] isaa)
357
throws IOException;
358
359
static {
360
IOUtil.load();
361
initIDs();
362
}
363
}
364
365