Skip to content

Commit 8ec378a

Browse files
committed
8277949: (dc) java/nio/channels/DatagramChannel/AdaptorBasic.java failed in timeout
Reviewed-by: jpai
1 parent c798316 commit 8ec378a

File tree

2 files changed

+61
-10
lines changed

2 files changed

+61
-10
lines changed

test/jdk/java/nio/channels/DatagramChannel/AdaptorBasic.java

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,8 @@
3636
import java.util.*;
3737
import java.lang.reflect.Field;
3838

39+
import jdk.test.lib.Platform;
40+
3941

4042
public class AdaptorBasic {
4143

@@ -69,6 +71,8 @@ static void test(DatagramSocket ds, InetSocketAddress dst, boolean shouldTimeout
6971
for (;;) {
7072
try {
7173
ds.receive(ip);
74+
// weed off stray datagrams
75+
if (ip.getPort() != dst.getPort()) continue;
7276
} catch (SocketTimeoutException x) {
7377
if (shouldTimeout) {
7478
out.println("Receive timed out, as expected");
@@ -111,12 +115,36 @@ static void test(InetSocketAddress dst,
111115
// Original
112116
ds = new DatagramSocket();
113117
} else {
114-
DatagramChannel dc = DatagramChannel.open();
115-
ds = dc.socket();
116-
ds.bind(new InetSocketAddress(0));
118+
int attempts = 0;
119+
DatagramChannel toclose = null;
120+
while (true) {
121+
DatagramChannel dc = DatagramChannel.open();
122+
ds = dc.socket();
123+
if (Platform.isOSX() && dst.getAddress().isLoopbackAddress()) {
124+
// avoid binding to the wildcard on macOS if possible, in order to limit
125+
// potential port conflict issues
126+
ds.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
127+
} else {
128+
ds.bind(new InetSocketAddress(0));
129+
}
130+
// on some systems it may be possible to bind two sockets
131+
// to the same port if one of them is bound to the wildcard,
132+
// if that happens, try again...
133+
if (ds.getLocalPort() == dst.getPort()) {
134+
if (toclose != null) toclose.close();
135+
toclose = dc;
136+
if (++attempts == 10) {
137+
throw new AssertionError("Couldn't allocate port for client socket");
138+
}
139+
continue;
140+
}
141+
if (toclose != null) toclose.close();
142+
break;
143+
}
117144
}
118145

119-
out.println("socket: " + ds);
146+
out.println("socket: " + ds + " bound to src: "
147+
+ ds.getLocalSocketAddress() + ", dst: " + dst);
120148
if (connect) {
121149
ds.connect(dst);
122150
out.println("connect: " + ds);
@@ -141,7 +169,7 @@ static void test(InetSocketAddress dst,
141169
public static void main(String[] args) throws Exception {
142170
// need an UDP echo server
143171
try (TestServers.UdpEchoServer echoServer
144-
= TestServers.UdpEchoServer.startNewServer(100)) {
172+
= TestServers.UdpEchoServer.startNewServer(100, InetAddress.getLoopbackAddress())) {
145173
final InetSocketAddress address
146174
= new InetSocketAddress(echoServer.getAddress(),
147175
echoServer.getPort());

test/jdk/java/nio/channels/TestServers.java

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -497,6 +497,7 @@ static abstract class AbstractUdpServer extends AbstractServer
497497
implements Runnable, Closeable {
498498

499499
protected final long linger; // #of ms to wait before responding
500+
protected final InetAddress bindAddress; //local address to bind to; can be null.
500501
private Thread acceptThread; // thread waiting for packets
501502
private DatagramSocket serverSocket; // the server socket
502503
private boolean started = false; // whether the server is started
@@ -509,7 +510,20 @@ static abstract class AbstractUdpServer extends AbstractServer
509510
* responding to requests.
510511
*/
511512
protected AbstractUdpServer(long linger) {
513+
this(linger, null);
514+
}
515+
516+
/**
517+
* Creates a new abstract UDP server.
518+
*
519+
* @param linger the amount of time the server should wait before
520+
* responding to requests.
521+
* @param bindAddress the address to bind to. If {@code null}, will
522+
* bind to InetAddress.getLocalHost();
523+
*/
524+
protected AbstractUdpServer(long linger, InetAddress bindAddress) {
512525
this.linger = linger;
526+
this.bindAddress = bindAddress;
513527
}
514528

515529
/**
@@ -574,8 +588,9 @@ public final synchronized void start() throws IOException {
574588
if (started) {
575589
return;
576590
}
591+
InetAddress lh = bindAddress == null ? InetAddress.getLocalHost() : bindAddress;
577592
final DatagramSocket socket =
578-
newDatagramSocket(0, InetAddress.getLocalHost());
593+
newDatagramSocket(0, lh);
579594
serverSocket = socket;
580595
acceptThread = new Thread(this);
581596
acceptThread.setDaemon(true);
@@ -759,7 +774,11 @@ public UdpEchoServer() {
759774
}
760775

761776
public UdpEchoServer(long linger) {
762-
super(linger);
777+
this(linger, null);
778+
}
779+
780+
public UdpEchoServer(long linger, InetAddress bindAddress) {
781+
super(linger, bindAddress);
763782
}
764783

765784
@Override
@@ -795,7 +814,11 @@ public static UdpEchoServer startNewServer() throws IOException {
795814
}
796815

797816
public static UdpEchoServer startNewServer(long linger) throws IOException {
798-
final UdpEchoServer echoServer = new UdpEchoServer(linger);
817+
return startNewServer(0, InetAddress.getLocalHost());
818+
}
819+
820+
public static UdpEchoServer startNewServer(long linger, InetAddress bindAddress) throws IOException {
821+
final UdpEchoServer echoServer = new UdpEchoServer(linger, bindAddress);
799822
echoServer.start();
800823
return echoServer;
801824
}

0 commit comments

Comments
 (0)