Skip to content

Commit 7f353cc

Browse files
committed
HBASE-24107 [Flakey Test] TestThriftServerCmdLine.testRunThriftServer NPEs if InfoServer port clash
1 parent 53299a6 commit 7f353cc

File tree

2 files changed

+78
-23
lines changed

2 files changed

+78
-23
lines changed

hbase-thrift/src/test/java/org/apache/hadoop/hbase/thrift/TestBindExceptionHandling.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,29 @@ public class TestBindExceptionHandling {
3232
HBaseClassTestRule.forClass(TestBindExceptionHandling.class);
3333

3434
/**
35-
* See if random port choosing works around port clashes
35+
* See if random port choosing works around protocol port clashes
3636
*/
3737
@Test
38-
public void testPortClash() {
38+
public void testProtocolPortClash() {
3939
ThriftServer thriftServer = null;
4040
try {
4141
thriftServer = new TestThriftServerCmdLine(null, false, false, false).
42-
createBoundServer(true);
42+
createBoundServer(true, false);
43+
assertNotNull(thriftServer.tserver);
44+
} finally {
45+
thriftServer.stop();
46+
}
47+
}
48+
49+
/**
50+
* See if random port choosing works around protocol port clashes
51+
*/
52+
@Test
53+
public void testInfoPortClash() {
54+
ThriftServer thriftServer = null;
55+
try {
56+
thriftServer = new TestThriftServerCmdLine(null, false, false, false).
57+
createBoundServer(false, true);
4358
assertNotNull(thriftServer.tserver);
4459
} finally {
4560
thriftServer.stop();

hbase-thrift/src/test/java/org/apache/hadoop/hbase/thrift/TestThriftServerCmdLine.java

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@
4949
import org.apache.thrift.transport.TFramedTransport;
5050
import org.apache.thrift.transport.TSocket;
5151
import org.apache.thrift.transport.TTransport;
52-
import org.apache.thrift.transport.TTransportException;
5352
import org.junit.AfterClass;
5453
import org.junit.BeforeClass;
5554
import org.junit.ClassRule;
@@ -175,16 +174,40 @@ private int getRandomPort() {
175174
* Server can fail to bind if clashing address. Add retrying until we get a good server.
176175
*/
177176
ThriftServer createBoundServer() {
178-
return createBoundServer(false);
177+
return createBoundServer(false, false);
178+
}
179+
180+
private ServerSocket getBoundSocket() {
181+
ServerSocket ss = null;
182+
while (true) {
183+
port = getRandomPort();
184+
try {
185+
ss = new ServerSocket();
186+
ss.bind(new InetSocketAddress(port));
187+
break;
188+
} catch (IOException ioe) {
189+
LOG.warn("Failed bind", ioe);
190+
try {
191+
ss.close();
192+
} catch (IOException ioe2) {
193+
LOG.warn("FAILED CLOSE of failed bind socket", ioe2);
194+
}
195+
}
196+
}
197+
return ss;
179198
}
180199

181200
/**
182-
* @param clash This param is just so we can manufacture a port clash so we can test the
183-
* code does the right thing when this happens during actual test runs. Ugly but works.
184-
* @see TestBindExceptionHandling#testPortClash()
201+
* @param protocolPortClash This param is just so we can manufacture a port clash so we can test
202+
* the code does the right thing when this happens during actual test runs. Ugly but works.
203+
* @see TestBindExceptionHandling#testProtocolPortClash()
185204
*/
186-
ThriftServer createBoundServer(boolean clash) {
187-
boolean testClashOfFirstPort = clash;
205+
ThriftServer createBoundServer(boolean protocolPortClash, boolean infoPortClash) {
206+
if (protocolPortClash && infoPortClash) {
207+
throw new RuntimeException("Can't set both at same time");
208+
}
209+
boolean testClashOfFirstProtocolPort = protocolPortClash;
210+
boolean testClashOfFirstInfoPort = infoPortClash;
188211
List<String> args = new ArrayList<>();
189212
ServerSocket ss = null;
190213
for (int i = 0; i < 100; i++) {
@@ -194,22 +217,26 @@ ThriftServer createBoundServer(boolean clash) {
194217
assertTrue(serverTypeOption.startsWith("-"));
195218
args.add(serverTypeOption);
196219
}
197-
port = getRandomPort();
198-
if (testClashOfFirstPort) {
220+
if (testClashOfFirstProtocolPort) {
199221
// Test what happens if already something bound to the socket.
200222
// Occupy the random port we just pulled.
201-
try {
202-
ss = new ServerSocket();
203-
ss.bind(new InetSocketAddress(port));
204-
} catch (IOException ioe) {
205-
LOG.warn("Failed bind", ioe);
206-
}
207-
testClashOfFirstPort = false;
223+
ss = getBoundSocket();
224+
port = ss.getLocalPort();
225+
testClashOfFirstProtocolPort = false;
226+
} else {
227+
port = getRandomPort();
208228
}
209229
args.add("-" + PORT_OPTION);
210230
args.add(String.valueOf(port));
211231
args.add("-" + INFOPORT_OPTION);
212-
int infoPort = getRandomPort();
232+
int infoPort;
233+
if (testClashOfFirstInfoPort) {
234+
ss = getBoundSocket();
235+
infoPort = ss.getLocalPort();
236+
testClashOfFirstInfoPort = false;
237+
} else {
238+
infoPort = getRandomPort();
239+
}
213240
args.add(String.valueOf(infoPort));
214241

215242
if (specifyFramed) {
@@ -230,9 +257,8 @@ ThriftServer createBoundServer(boolean clash) {
230257
for (int ii = 0; ii < 100 && (thriftServer.tserver == null); ii++) {
231258
Threads.sleep(100);
232259
}
233-
if (cmdLineException instanceof TTransportException &&
234-
cmdLineException.getCause() instanceof BindException) {
235-
LOG.info("Trying new port", cmdLineException);
260+
if (isBindException(cmdLineException)) {
261+
LOG.info("BindException; trying new port", cmdLineException);
236262
cmdLineException = null;
237263
thriftServer.stop();
238264
continue;
@@ -253,6 +279,20 @@ ThriftServer createBoundServer(boolean clash) {
253279
return thriftServer;
254280
}
255281

282+
private boolean isBindException(Exception cmdLineException) {
283+
if (cmdLineException == null) {
284+
return false;
285+
}
286+
if (cmdLineException instanceof BindException) {
287+
return true;
288+
}
289+
if (cmdLineException.getCause() != null &&
290+
cmdLineException.getCause() instanceof BindException) {
291+
return true;
292+
}
293+
return false;
294+
}
295+
256296
@Test
257297
public void testRunThriftServer() throws Exception {
258298
ThriftServer thriftServer = createBoundServer();

0 commit comments

Comments
 (0)