|
19 | 19 | import java.io.File; |
20 | 20 | import java.io.PrintWriter; |
21 | 21 | import java.io.StringWriter; |
| 22 | +import java.net.BindException; |
22 | 23 | import java.util.ArrayList; |
23 | 24 | import java.util.Arrays; |
24 | 25 | import java.util.Collection; |
|
177 | 178 | @SuppressWarnings("deprecation") |
178 | 179 | public abstract class AbstractDebugTest extends TestCase implements IEvaluationListener { |
179 | 180 |
|
| 181 | + private static final int SOCKET_BIND_ERROR_MAX_RETRIES = 3; |
180 | 182 | private static boolean setupFirstTest = false; |
181 | 183 |
|
182 | 184 | public static final String MULTI_OUTPUT_PROJECT_NAME = "MultiOutput"; |
@@ -1490,13 +1492,7 @@ protected Object launchAndWait(ILaunchConfiguration configuration, DebugEventWai |
1490 | 1492 | * if the event is never received. |
1491 | 1493 | */ |
1492 | 1494 | protected Object launchAndWait(ILaunchConfiguration configuration, String mode, DebugEventWaiter waiter, boolean register) throws CoreException { |
1493 | | - ILaunch launch; |
1494 | | - try { |
1495 | | - launch = configuration.launch(mode, new TimeoutMonitor(DEFAULT_TIMEOUT), false, register); |
1496 | | - } catch (Throwable t) { |
1497 | | - logProcessConsoleContents(); |
1498 | | - throw t; |
1499 | | - } |
| 1495 | + ILaunch launch = launchConfig(configuration, mode, register); |
1500 | 1496 | Object suspendee= waiter.waitForEvent(); |
1501 | 1497 | if (suspendee == null) { |
1502 | 1498 | StringBuilder buf = new StringBuilder(); |
@@ -1539,8 +1535,6 @@ protected Object launchAndWait(ILaunchConfiguration configuration, String mode, |
1539 | 1535 | return suspendee; |
1540 | 1536 | } |
1541 | 1537 |
|
1542 | | - |
1543 | | - |
1544 | 1538 | /** |
1545 | 1539 | * Launches the type with the given name, and waits for a |
1546 | 1540 | * suspend event in that program. Returns the thread in which the suspend |
@@ -3224,6 +3218,28 @@ private static void logVMChange(String message, IVMInstall vm) { |
3224 | 3218 | JDIDebugPlugin.log(status); |
3225 | 3219 | } |
3226 | 3220 |
|
| 3221 | + private static ILaunch launchConfig(ILaunchConfiguration configuration, String mode, boolean register) throws CoreException { |
| 3222 | + ILaunch launch = null; |
| 3223 | + for (int retry = 1; retry <= SOCKET_BIND_ERROR_MAX_RETRIES; ++retry) { |
| 3224 | + try { |
| 3225 | + launch = configuration.launch(mode, new TimeoutMonitor(DEFAULT_TIMEOUT), false, register); |
| 3226 | + break; |
| 3227 | + } catch (CoreException e) { |
| 3228 | + Throwable cause = e.getStatus().getException(); |
| 3229 | + if (retry < SOCKET_BIND_ERROR_MAX_RETRIES && cause instanceof BindException) { |
| 3230 | + // port might be in use between checking for a free port and launching, try a few times |
| 3231 | + DebugPlugin.log(Status.error("Could not bind socket for debugging, retry: " + retry, e)); |
| 3232 | + } else { |
| 3233 | + throw e; |
| 3234 | + } |
| 3235 | + } catch (Throwable t) { |
| 3236 | + logProcessConsoleContents(); |
| 3237 | + throw t; |
| 3238 | + } |
| 3239 | + } |
| 3240 | + return launch; |
| 3241 | + } |
| 3242 | + |
3227 | 3243 | private static void logProcessConsoleContents() { |
3228 | 3244 | try { |
3229 | 3245 | StringBuilder buf = new StringBuilder(); |
|
0 commit comments