From fa79d364cc8818616ee7f0d727aa57adb40b6597 Mon Sep 17 00:00:00 2001 From: John Cortell Date: Wed, 3 Mar 2010 18:54:09 +0000 Subject: [PATCH] [304561] While-target-running breakpoint tests are failing because of Windows gdb bug --- .../dsf/gdb/tests/MIBreakpointsTest.java | 98 ++++++++++++++++--- 1 file changed, 82 insertions(+), 16 deletions(-) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIBreakpointsTest.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIBreakpointsTest.java index 3c3fedc39bd..9024635af3c 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIBreakpointsTest.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIBreakpointsTest.java @@ -53,6 +53,7 @@ import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner; import org.eclipse.cdt.tests.dsf.gdb.framework.BaseTestCase; import org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil; import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin; +import org.eclipse.core.runtime.Platform; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; @@ -1218,12 +1219,10 @@ public class MIBreakpointsTest extends BaseTestCase { MIBreakpointDMContext ref = (MIBreakpointDMContext) insertBreakpoint(fBreakpointsDmc, breakpoint); assertTrue(fWait.getMessage(), fWait.isOK()); - // Wait for breakpoint to hit. The program terminates after the sleep() - // call, so waiting four seconds is more than enough - MIStoppedEvent event = SyncUtil.waitForStop(4000); + // Wait for breakpoint to hit. + MIStoppedEvent event = waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(true, 2); - // Ensure the correct BreakpointEvent was received - waitForBreakpointEvent(2); + // Ensure the correct BreakpointEvent was received MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref); assertTrue("BreakpointEvent problem: expected " + 2 + " BREAKPOINT event(s), received " + fBreakpointEventCount, fBreakpointEventCount == 2); @@ -1404,10 +1403,9 @@ public class MIBreakpointsTest extends BaseTestCase { assertTrue(fWait.getMessage(), fWait.isOK()); // Wait for breakpoint to hit - MIStoppedEvent event = SyncUtil.waitForStop(); + MIStoppedEvent event = waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(true, 2); // Ensure that right BreakpointEvents were received - waitForBreakpointEvent(2); assertTrue("BreakpointEvent problem: expected " + 2 + " BREAKPOINT event(s), received " + fBreakpointEventCount, fBreakpointEventCount == 2); assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received " @@ -1695,10 +1693,10 @@ public class MIBreakpointsTest extends BaseTestCase { removeBreakpoint(ref); assertTrue(fWait.getMessage(), fWait.isOK()); - MIStoppedEvent event = SyncUtil.waitForStop(); + // Wait for the breakpoint to hit + MIStoppedEvent event = waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(true, 4); // Ensure the correct BreakpointEvent was received - waitForBreakpointEvent(4); assertTrue("BreakpointEvent problem: expected " + 4 + " BREAKPOINT event(s), received " + fBreakpointEventCount, fBreakpointEventCount == 4); assertTrue("BreakpointEvent problem: expected " + 2 + " BREAKPOINT_HIT event(s), received " @@ -1920,10 +1918,10 @@ public class MIBreakpointsTest extends BaseTestCase { updateBreakpoint(ref, delta); assertTrue(fWait.getMessage(), fWait.isOK()); - MIStoppedEvent event = SyncUtil.waitForStop(); + // Wait for the breakpoint to hit + MIStoppedEvent event = waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(true, 2); // Ensure that right BreakpointEvents were received - waitForBreakpointEvent(2); assertTrue("BreakpointEvent problem: expected " + 2 + " BREAKPOINT event(s), received " + fBreakpointEventCount, fBreakpointEventCount == 2); assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_UPDATED event(s), received " @@ -2288,10 +2286,10 @@ public class MIBreakpointsTest extends BaseTestCase { updateBreakpoint(ref, delta); assertTrue(fWait.getMessage(), fWait.isOK()); - MIStoppedEvent event = SyncUtil.waitForStop(); + // Wait for the breakpoint to hit + MIStoppedEvent event = waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(true, 2); // Ensure that right BreakpointEvents were received - waitForBreakpointEvent(2); assertTrue("BreakpointEvent problem: expected " + 2 + " BREAKPOINT event(s), received " + fBreakpointEventCount, fBreakpointEventCount == 2); assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_UPDATED event(s), received " @@ -2411,7 +2409,7 @@ public class MIBreakpointsTest extends BaseTestCase { assertTrue(fWait.getMessage(), fWait.isOK()); // Ensure that right BreakpointEvents were received - waitForBreakpointEvent(2); + waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(false, 2); assertTrue("BreakpointEvent problem: expected " + 2 + " BREAKPOINT event(s), received " + fBreakpointEventCount, fBreakpointEventCount == 2); assertTrue("BreakpointEvent problem: expected " + 2 + " BREAKPOINT_ADDED event(s), received " @@ -2595,10 +2593,10 @@ public class MIBreakpointsTest extends BaseTestCase { updateBreakpoint(ref, delta); assertTrue(fWait.getMessage(), fWait.isOK()); - MIStoppedEvent event = SyncUtil.waitForStop(); + // Wait for the breakpoint to hit + MIStoppedEvent event = waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(true, 2); // Ensure that right BreakpointEvents were received - waitForBreakpointEvent(2); assertTrue("BreakpointEvent problem: expected " + 2 + " BREAKPOINT event(s), received " + fBreakpointEventCount, fBreakpointEventCount == 2); assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_UPDATED event(s), received " @@ -3254,4 +3252,72 @@ public class MIBreakpointsTest extends BaseTestCase { watchpoint1 == null); } + /** + * This method allows the while-target-running tests to side-step a bug in + * Windows gdb. To perform a breakpoint operation while the target is + * running, the DSF debugger temporarily suspends the target (gdb) with a + * SIGINT, carries out the operation, and then resumes the target. On + * Windows gdbs, there's a race condition problem with the SIGINT handling + * resulting in the target suspending for a reason other than the SIGINT. + * Resuming the target, though, will result in the target suspending + * again...this time for the SIGINT. + * + * See http://sourceware.org/ml/gdb-patches/2008-05/msg00264.html + * + * I've looked at the latest gdb sources and the problem has not yet been + * fixed. Search "FIXME: brobecker/2008-05-20" in windows-nat.c + * + * @param waitForStop + * indicates whether we should first wait for the target to stop. + * Otherwise we just wait until [eventCount] number of breakpoint + * events have occurred. If this arg is true, we return the + * MIStoppedEvent. + * @param eventCount + * the number of breakpoint events to wait for + * @return the stopped event, if [waitForStop] is true; otherwise null + * @throws Throwable + */ + MIStoppedEvent waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(boolean waitForStop, int eventCount) throws Throwable { + MIStoppedEvent event = null; + if (waitForStop) { + // The target program should be in the middle of a one second + // sleep() call. Most tests involve setting a breakpoint at + // some line after the sleep call. Allow up to three seconds + // for the sleep() call to complete and the breakpoint to be + // hit. + event = SyncUtil.waitForStop(3000); + } + + if (Platform.getOS().equals(Platform.OS_WIN32)) { + // Normally, we would now give a couple of seconds for any + // additional expected breakpoint events to occur after the target's + // sleep call returns and fail the test if they don't. But the + // Windws gdb bug may have gotten in the way. If it has, the target + // is in an unexpected suspended state instead of running or stopped + // at the test breakpoint. We just don't know. So, we wait two + // seconds in case everything is actually behaving normally, since + // that's how patient waitForBreakpointEvent() is. If waitForStop is + // false, we need to allow enough time for the sleep() to return AND + // any subsequent breakpoint events to occur. + Thread.sleep(TestsPlugin.massageTimeout(waitForStop ? 2000 : 5000)); + + assertTrue("We should have gotten at least one breakpoint event", fBreakpointEventCount >= 1); + if (fBreakpointEventCount < eventCount) { + // It's likely we ran into the gdb bug. We can ignore it (since + // it's out of our control) and proceed to test whether the + // breakpoint operation was properly carried out. + System.out.println("Performing an additional resume to work around Windows gdb bug"); + SyncUtil.resume(); + if (waitForStop) { + event = SyncUtil.waitForStop(4000); + } + } + } + + // OK, at this point, all the expected breakpoint events should have + // occurred, or we really have a problem (unrelated to the gdb bug) + waitForBreakpointEvent(eventCount); + + return event; + } }