This is an automated email from the ASF dual-hosted git repository. entl pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/netbeans.git
commit fd6921c496c53e51f8c451dee46887545c9d0ca7 Author: Martin Entlicher <martin.entlic...@oracle.com> AuthorDate: Fri May 21 10:58:13 2021 +0200 Assure that debug process exits when debugging finishes. --- .../modules/cpplite/debugger/CPPLiteDebugger.java | 72 ++++++++++++++------ .../cpplite/debugger/AbstractDebugTest.java | 14 +++- .../modules/cpplite/debugger/BreakpointsTest.java | 1 + .../debugger/{StepTest.java => ExitTest.java} | 76 ++++++++++------------ .../modules/cpplite/debugger/StepTest.java | 3 +- 5 files changed, 103 insertions(+), 63 deletions(-) diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteDebugger.java b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteDebugger.java index 8545d3f..0c41c83 100644 --- a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteDebugger.java +++ b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteDebugger.java @@ -36,6 +36,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.Logger; @@ -93,6 +94,7 @@ public final class CPPLiteDebugger { private final ThreadsCollector threadsCollector = new ThreadsCollector(this); private volatile CPPThread currentThread; private volatile CPPFrame currentFrame; + private AtomicInteger exitCode = new AtomicInteger(); public CPPLiteDebugger(ContextProvider contextProvider) { this.contextProvider = contextProvider; @@ -359,6 +361,13 @@ public final class CPPLiteDebugger { } void finish (boolean sendExit) { + finish(sendExit, 0); + } + + private void finish (boolean sendExit, int exitCode) { + if (exitCode != 0) { + this.exitCode.set(exitCode); + } LOGGER.fine("CPPLiteDebugger.finish()"); if (finished) { LOGGER.fine("finish(): already finished."); @@ -462,29 +471,43 @@ public final class CPPLiteDebugger { } CPPThread thread = threadsCollector.get(threadId); String reason = results.getConstValue("reason", ""); - switch (reason) { - case "exited-normally": - if ('*' == record.type()) { - finish(false); + if (reason.startsWith("exited")) { + if ('*' == record.type()) { + int exitCode; + if ("exited-normally".equals(reason)) { + exitCode = 0; } else { - threadsCollector.remove(threadId); - } - break; - default: - MITList topFrameList = (MITList) results.valueOf("frame"); - CPPFrame frame = topFrameList != null ? CPPFrame.create(thread, topFrameList) : null; - thread.setTopFrame(frame); - setSuspended(true, thread, frame); - if (frame != null) { - Line currentLine = frame.location(); - if (currentLine != null) { - Annotatable[] lines = new Annotatable[] {currentLine}; - CPPLiteDebugger.this.currentLine = lines; - Utils.markCurrent(lines); - Utils.showLine(lines); + String exitCodeStr = results.getConstValue("exit-code", null); + if (exitCodeStr != null) { + if (exitCodeStr.startsWith("0x")) { + exitCode = Integer.parseInt(exitCodeStr, 16); + } else if (exitCodeStr.startsWith("0")) { + exitCode = Integer.parseInt(exitCodeStr, 8); + } else { + exitCode = Integer.parseInt(exitCodeStr); + } + } else { + exitCode = 0; } } - break; + finish(true, exitCode); + } else { + threadsCollector.remove(threadId); + } + } else { + MITList topFrameList = (MITList) results.valueOf("frame"); + CPPFrame frame = topFrameList != null ? CPPFrame.create(thread, topFrameList) : null; + thread.setTopFrame(frame); + setSuspended(true, thread, frame); + if (frame != null) { + Line currentLine = frame.location(); + if (currentLine != null) { + Annotatable[] lines = new Annotatable[] {currentLine}; + CPPLiteDebugger.this.currentLine = lines; + Utils.markCurrent(lines); + Utils.showLine(lines); + } + } } break; case "running": @@ -668,6 +691,7 @@ public final class CPPLiteDebugger { } }); debugger.setDebuggee(debuggee); + AtomicInteger exitCode = debugger.exitCode; return Pair.of(es[0], new Process() { @Override @@ -686,8 +710,14 @@ public final class CPPLiteDebugger { } @Override + public boolean isAlive() { + return debuggee.isAlive(); + } + + @Override public int waitFor() throws InterruptedException { - return debuggee.waitFor(); + debuggee.waitFor(); + return exitCode.get(); } @Override diff --git a/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/AbstractDebugTest.java b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/AbstractDebugTest.java index eb1e626..96c38b1 100644 --- a/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/AbstractDebugTest.java +++ b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/AbstractDebugTest.java @@ -27,11 +27,13 @@ import junit.framework.Test; import org.netbeans.api.debugger.DebuggerEngine; import org.netbeans.junit.NbModuleSuite; import org.netbeans.junit.NbTestCase; +import org.openide.util.Pair; public abstract class AbstractDebugTest extends NbTestCase { protected DebuggerEngine engine; protected CPPLiteDebugger debugger; + protected Process process; private final int[] suspendCount = new int[]{0}; private final int[] resumeCount = new int[]{0}; @@ -51,7 +53,9 @@ public abstract class AbstractDebugTest extends NbTestCase { } protected final void startDebugging(String name, File wd) throws IOException { - engine = CPPLiteDebugger.startDebugging(new CPPLiteDebuggerConfig(Arrays.asList(new File(wd, name).getAbsolutePath()), wd, "gdb")).first(); + Pair<DebuggerEngine, Process> engineProcess = CPPLiteDebugger.startDebugging(new CPPLiteDebuggerConfig(Arrays.asList(new File(wd, name).getAbsolutePath()), wd, "gdb")); + engine = engineProcess.first(); + process = engineProcess.second(); debugger = engine.lookupFirst(null, CPPLiteDebugger.class); debugger.addStateListener(new CPPLiteDebugger.StateListener() { @Override @@ -99,6 +103,14 @@ public abstract class AbstractDebugTest extends NbTestCase { } } + protected boolean isAppProcessAlive() { + return process.isAlive(); + } + + protected final int waitAppProcessExit() throws InterruptedException { + return process.waitFor(); + } + protected final void assertStoppedAt(URI file, int line) { CPPFrame currentFrame = debugger.getCurrentFrame(); assertNotNull(currentFrame); diff --git a/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/BreakpointsTest.java b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/BreakpointsTest.java index d22f578..cf43cf9 100644 --- a/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/BreakpointsTest.java +++ b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/BreakpointsTest.java @@ -135,6 +135,7 @@ public class BreakpointsTest extends AbstractDebugTest { waitResumed(6); engine.getActionsManager().doAction(ActionsManager.ACTION_KILL); + assertEquals(0, waitAppProcessExit()); } public static Test suite() { diff --git a/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/StepTest.java b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/ExitTest.java similarity index 54% copy from cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/StepTest.java copy to cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/ExitTest.java index 307af7a..2d76f7b 100644 --- a/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/StepTest.java +++ b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/ExitTest.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.netbeans.modules.cpplite.debugger; import java.io.File; @@ -24,10 +23,11 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import junit.framework.Test; - +import static junit.framework.TestCase.assertNotNull; import org.netbeans.api.debugger.ActionsManager; import org.netbeans.api.debugger.DebuggerManager; import org.netbeans.junit.NbModuleSuite; +import static org.netbeans.modules.cpplite.debugger.AbstractDebugTest.compileCPP; import org.netbeans.modules.cpplite.debugger.breakpoints.CPPLiteBreakpoint; import org.openide.cookies.LineCookie; import org.openide.filesystems.FileObject; @@ -35,64 +35,60 @@ import org.openide.filesystems.FileUtil; import org.openide.loaders.DataObject; /** - * Tests C/C++ debugger stepping actions: step in, step out and step over. * - * @author Jan Jancura + * @author Martin Entlicher */ -public class StepTest extends AbstractDebugTest { +public class ExitTest extends AbstractDebugTest { - public StepTest (String s) { - super (s); + public ExitTest(String s) { + super(s); } - @Override - protected void setUp() throws Exception { - clearWorkDir(); + public void testAppExit () throws Exception { + File wd = getWorkDir(); + for (int exitCode = 0; exitCode <= 200; exitCode += 100) { + FileObject source = FileUtil.createData(FileUtil.toFileObject(wd), "mainExit" + exitCode + ".cpp"); + try (OutputStream os = source.getOutputStream(); + Writer w = new OutputStreamWriter(os)) { + w.append("int main(int argc, char** args) {\n" + + " int N = 100;\n" + + " return " + exitCode + ";\n" + + "}"); + } + compileCPP("mainExit" + exitCode, wd); + LineCookie lc = DataObject.find(source).getLookup().lookup(LineCookie.class); + assertNotNull(lc); + DebuggerManager.getDebuggerManager().addBreakpoint(CPPLiteBreakpoint.create(lc.getLineSet().getCurrent(4))); + startDebugging("mainExit" + exitCode, wd); + assertEquals(exitCode, waitAppProcessExit()); + } } - public void testStepOver () throws Exception { + public void testAppKill () throws Exception { File wd = getWorkDir(); - FileObject source = FileUtil.createData(FileUtil.toFileObject(wd), "main.cpp"); + FileObject source = FileUtil.createData(FileUtil.toFileObject(wd), "mainKill.cpp"); try (OutputStream os = source.getOutputStream(); Writer w = new OutputStreamWriter(os)) { - w.append("#include <iostream>\n" + - "\n" + - "void test(void) {\n" + - " std::cerr << \"Hello, from err!\" << std::endl;\n" + - " std::cout << \"Hello, second time!\" << std::endl;\n" + - "}\n" + - "\n" + - "int main(void) {\n" + - " int i = 42;\n" + - " std::cout << \"Hello, world!\" << std::endl;\n" + - " test();\n" + - " std::cout << \"Hello, second time!\" << std::endl;\n" + + w.append("int main(int argc, char** args) {\n" + + " for(;;);\n" + "}"); } - compileCPP("main", wd); + compileCPP("mainKill", wd); LineCookie lc = DataObject.find(source).getLookup().lookup(LineCookie.class); assertNotNull(lc); DebuggerManager.getDebuggerManager().addBreakpoint(CPPLiteBreakpoint.create(lc.getLineSet().getCurrent(4))); - startDebugging("main", wd); - - waitSuspended(1); - - assertStoppedAt(source.toURI(), 5); - - engine.getActionsManager().doAction(ActionsManager.ACTION_STEP_OVER); - - waitResumed(1); - - waitSuspended(2); - - assertStoppedAt(source.toURI(), 6); - + startDebugging("mainKill", wd); + assertTrue(isAppProcessAlive()); + Thread.sleep(10); + assertTrue(isAppProcessAlive()); engine.getActionsManager().doAction(ActionsManager.ACTION_KILL); + assertEquals(0, waitAppProcessExit()); + assertFalse(isAppProcessAlive()); } public static Test suite() { return NbModuleSuite.emptyConfiguration() - .addTest(StepTest.class) + .addTest(ExitTest.class) .enableModules(".*", ".*") .gui(false) .suite(); diff --git a/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/StepTest.java b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/StepTest.java index 307af7a..7283499 100644 --- a/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/StepTest.java +++ b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/StepTest.java @@ -87,7 +87,8 @@ public class StepTest extends AbstractDebugTest { assertStoppedAt(source.toURI(), 6); - engine.getActionsManager().doAction(ActionsManager.ACTION_KILL); + engine.getActionsManager().doAction(ActionsManager.ACTION_CONTINUE); + assertEquals(0, waitAppProcessExit()); } public static Test suite() { --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org For additional commands, e-mail: commits-h...@netbeans.apache.org For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists