Skip to content

Commit b2f4dff

Browse files
committedNov 15, 2021
8269481: SctpMultiChannel never releases own file descriptor
Backport-of: d1cecaaa22d551b93074c33209dac7354f4b6932
1 parent c3de885 commit b2f4dff

File tree

4 files changed

+142
-3
lines changed

4 files changed

+142
-3
lines changed
 

‎src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -640,15 +640,16 @@ public void kill() throws IOException {
640640
return;
641641
if (state == ChannelState.UNINITIALIZED) {
642642
state = ChannelState.KILLED;
643+
SctpNet.close(fdVal);
643644
return;
644645
}
645646
assert !isOpen() && !isRegistered();
646647

647648
/* Postpone the kill if there is a waiting reader
648649
* or writer thread. */
649650
if (receiverThread == 0 && senderThread == 0) {
650-
SctpNet.close(fdVal);
651651
state = ChannelState.KILLED;
652+
SctpNet.close(fdVal);
652653
} else {
653654
state = ChannelState.KILLPENDING;
654655
}

‎src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -374,14 +374,15 @@ public void kill() throws IOException {
374374
return;
375375
if (state == ChannelState.UNINITIALIZED) {
376376
state = ChannelState.KILLED;
377+
SctpNet.close(fdVal);
377378
return;
378379
}
379380
assert !isOpen() && !isRegistered();
380381

381382
/* Postpone the kill if there is a thread sending or receiving. */
382383
if (receiverThread == 0 && senderThread == 0) {
383-
SctpNet.close(fdVal);
384384
state = ChannelState.KILLED;
385+
SctpNet.close(fdVal);
385386
} else {
386387
state = ChannelState.KILLPENDING;
387388
}

‎src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -282,14 +282,15 @@ public void kill() throws IOException {
282282
return;
283283
if (state == ChannelState.UNINITIALIZED) {
284284
state = ChannelState.KILLED;
285+
SctpNet.close(fdVal);
285286
return;
286287
}
287288
assert !isOpen() && !isRegistered();
288289

289290
// Postpone the kill if there is a thread in accept
290291
if (thread == 0) {
291-
SctpNet.close(fdVal);
292292
state = ChannelState.KILLED;
293+
SctpNet.close(fdVal);
293294
} else {
294295
state = ChannelState.KILLPENDING;
295296
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
* Copyright (c) 2021, 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.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/* @test
25+
* @bug 8269481
26+
* @summary Tests that file descriptors are closed
27+
* @requires (os.family == "linux")
28+
* @run main/othervm CloseDescriptors
29+
*/
30+
31+
import java.net.InetSocketAddress;
32+
import java.net.ServerSocket;
33+
import java.nio.ByteBuffer;
34+
import java.nio.file.Files;
35+
import java.nio.file.Path;
36+
import java.util.List;
37+
import java.util.Optional;
38+
import com.sun.nio.sctp.MessageInfo;
39+
import com.sun.nio.sctp.SctpMultiChannel;
40+
41+
public class CloseDescriptors {
42+
43+
private static final int NUM = 5;
44+
private static final int SIZE = 1024;
45+
private static final int MAX_DESC = 3;
46+
47+
public static void main(String[] args) throws Exception {
48+
if (!Util.isSCTPSupported()) {
49+
System.out.println("SCTP protocol is not supported");
50+
System.out.println("Test cannot be run");
51+
return;
52+
}
53+
54+
List<String> lsofDirs = List.of("/usr/bin", "/usr/sbin");
55+
Optional<Path> lsof = lsofDirs.stream()
56+
.map(s -> Path.of(s, "lsof"))
57+
.filter(f -> Files.isExecutable(f))
58+
.findFirst();
59+
if (!lsof.isPresent()) {
60+
System.out.println("Cannot locate lsof in " + lsofDirs);
61+
System.out.println("Test cannot be run");
62+
return;
63+
}
64+
65+
try (ServerSocket ss = new ServerSocket(0)) {
66+
int port = ss.getLocalPort();
67+
68+
Thread server = new Server(port);
69+
server.start();
70+
Thread.sleep(100); // wait for server to be ready
71+
72+
System.out.println("begin");
73+
for (int i = 0; i < 5; ++i) {
74+
System.out.println(i);
75+
doIt(port);
76+
Thread.sleep(100);
77+
}
78+
System.out.println("end");
79+
server.join();
80+
}
81+
82+
long pid = ProcessHandle.current().pid();
83+
ProcessBuilder pb = new ProcessBuilder(
84+
lsof.get().toString(), "-U", "-a", "-p", Long.toString(pid));
85+
Process p = pb.start();
86+
Object[] lines = p.inputReader().lines().toArray();
87+
p.waitFor();
88+
89+
int nfds = lines.length - 1;
90+
if (nfds > MAX_DESC) {
91+
throw new RuntimeException("Number of open descriptors " +
92+
nfds + " > " + MAX_DESC);
93+
}
94+
}
95+
96+
static void doIt(int port) throws Exception {
97+
InetSocketAddress sa = new InetSocketAddress("localhost", port);
98+
99+
for (int i = 0; i < NUM; ++i) {
100+
System.out.println(" " + i);
101+
SctpMultiChannel channel = SctpMultiChannel.open();
102+
channel.configureBlocking(true);
103+
MessageInfo info = MessageInfo.createOutgoing(sa, 0);
104+
ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE);
105+
channel.send(buffer, info);
106+
channel.close();
107+
108+
Thread.sleep(200);
109+
}
110+
}
111+
112+
static class Server extends Thread {
113+
int port;
114+
115+
Server(int port) {
116+
this.port = port;
117+
}
118+
119+
@Override
120+
public void run() {
121+
for (int i = 0; i < NUM; i++) {
122+
try {
123+
SctpMultiChannel sm = SctpMultiChannel.open();
124+
InetSocketAddress sa =
125+
new InetSocketAddress("localhost", port);
126+
sm.bind(sa);
127+
ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE);
128+
MessageInfo info = sm.receive(buffer, null, null);
129+
sm.close();
130+
} catch (Exception e) {
131+
e.printStackTrace();
132+
}
133+
}
134+
}
135+
}
136+
}

1 commit comments

Comments
 (1)

openjdk-notifier[bot] commented on Nov 15, 2021

@openjdk-notifier[bot]
Please sign in to comment.