From d2cd2d381f9cd10923bf2d30ce1a3e904d4bee3c Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Fri, 26 Feb 2010 13:56:49 +0000 Subject: [PATCH] [302597] For MIStopped event that don't contain a threadId we must ask the backend for the threadId --- .../cdt/dsf/mi/service/MIRunControl.java | 25 +++++++- .../mi/service/command/CLIEventProcessor.java | 17 +++-- .../command/MIRunControlEventProcessor.java | 37 +++++------ .../service/command/commands/CLIThread.java | 37 +++++++++++ .../service/command/output/CLIThreadInfo.java | 63 +++++++++++++++++++ 5 files changed, 148 insertions(+), 31 deletions(-) create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIThread.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/CLIThreadInfo.java diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRunControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRunControl.java index ffe38459957..44e8bac3daa 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRunControl.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRunControl.java @@ -32,6 +32,7 @@ import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent; import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; import org.eclipse.cdt.dsf.mi.service.command.commands.CLIJump; +import org.eclipse.cdt.dsf.mi.service.command.commands.CLIThread; import org.eclipse.cdt.dsf.mi.service.command.commands.MICommand; import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecContinue; import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecFinish; @@ -54,6 +55,7 @@ import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent; import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadCreatedEvent; import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadExitEvent; import org.eclipse.cdt.dsf.mi.service.command.events.MIWatchpointTriggerEvent; +import org.eclipse.cdt.dsf.mi.service.command.output.CLIThreadInfo; import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; import org.eclipse.cdt.dsf.mi.service.command.output.MIThreadListIdsInfo; import org.eclipse.cdt.dsf.service.AbstractDsfService; @@ -381,10 +383,29 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I IDMEvent event = null; // Find the container context, which is used in multi-threaded debugging. - IContainerDMContext containerDmc = DMContexts.getAncestorOfType(e.getDMContext(), IContainerDMContext.class); + final IContainerDMContext containerDmc = DMContexts.getAncestorOfType(e.getDMContext(), IContainerDMContext.class); if (containerDmc != null) { - // Set the triggering context only if it's different than the container context. + // Set the triggering context only if it's not the container context, since we are looking for a thread. IExecutionDMContext triggeringCtx = !e.getDMContext().equals(containerDmc) ? e.getDMContext() : null; + if (triggeringCtx == null) { + // Still no thread. Let's ask the bakend for one. + // We need a proper thread id for the debug view to select the right thread + // Bug 300096 comment #15 and Bug 302597 + getConnection().queueCommand( + new CLIThread(containerDmc), + new DataRequestMonitor(getExecutor(), null) { + @Override + protected void handleCompleted() { + IExecutionDMContext triggeringCtx2 = null; + if (isSuccess() && getData().getCurrentThread() != null) { + triggeringCtx2 = createMIExecutionContext(containerDmc, getData().getCurrentThread()); + } + IDMEvent event2 = new ContainerSuspendedEvent(containerDmc, e, triggeringCtx2); + getSession().dispatchEvent(event2, getProperties()); + } + }); + return; + } event = new ContainerSuspendedEvent(containerDmc, e, triggeringCtx); } else { event = new SuspendedEvent(e.getDMContext(), e); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CLIEventProcessor.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CLIEventProcessor.java index 7c8bbb6decd..f32098a9472 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CLIEventProcessor.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CLIEventProcessor.java @@ -156,16 +156,7 @@ public class CLIEventProcessor } private void processStateChanges(int token, String operation) { - // Get the command name. - int indx = operation.indexOf(' '); - if (indx != -1) { - operation = operation.substring(0, indx).trim(); - } else { - operation = operation.trim(); - } - // Check the type of command - int type = getSteppingOperationKind(operation); if (type != -1) { // if it was a step instruction set state running @@ -237,6 +228,14 @@ public class CLIEventProcessor } private static int getSteppingOperationKind(String operation) { + // Get the command name. + int indx = operation.indexOf(' '); + if (indx != -1) { + operation = operation.substring(0, indx).trim(); + } else { + operation = operation.trim(); + } + int type = -1; /* execution commands: n, next, s, step, si, stepi, u, until, finish, return, c, continue, fg */ diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIRunControlEventProcessor.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIRunControlEventProcessor.java index d9f37479f29..9bd691e2807 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIRunControlEventProcessor.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIRunControlEventProcessor.java @@ -14,8 +14,6 @@ package org.eclipse.cdt.dsf.mi.service.command; import java.util.LinkedList; import java.util.List; -import org.eclipse.cdt.dsf.datamodel.DMContexts; -import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.debug.service.IRunControl; import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext; @@ -292,24 +290,23 @@ public class MIRunControlEventProcessor // when it stops due to a CLI command. We have to trigger the // MIStoppedEvent ourselves if (cmd instanceof CLICommand) { - IRunControl runControl = fServicesTracker.getService(IRunControl.class); - if (runControl != null) { - IDMContext dmc = ((CLICommand)cmd).getContext(); - IExecutionDMContext execDmc = - DMContexts.getAncestorOfType(dmc, IExecutionDMContext.class); - - if (execDmc == null) { - IMIProcesses procService = fServicesTracker.getService(IMIProcesses.class); - if (procService != null) { - String groupId = MIProcesses.UNIQUE_GROUP_ID; - IProcessDMContext procDmc = procService.createProcessContext(fControlDmc, groupId); - execDmc = procService.createContainerContext(procDmc, groupId); - } - } - if (execDmc != null && runControl.isSuspended(execDmc) == false) { - MIEvent event = MIStoppedEvent.parse(execDmc, id, rr.getMIResults()); - fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties()); - } + // It is important to limit this to runControl operations (e.g., 'next', 'continue', 'jump') + // There are other CLI commands that we use that could still be sent when the target is considered + // running, due to timing issues. + if (CLIEventProcessor.isSteppingOperation(((CLICommand)cmd).getOperation())) { + IRunControl runControl = fServicesTracker.getService(IRunControl.class); + IMIProcesses procService = fServicesTracker.getService(IMIProcesses.class); + if (runControl != null && procService != null) { + // We don't know which thread stopped so we simply create a container event. + String groupId = MIProcesses.UNIQUE_GROUP_ID; + IProcessDMContext procDmc = procService.createProcessContext(fControlDmc, groupId); + IContainerDMContext processContainerDmc = procService.createContainerContext(procDmc, groupId); + + if (runControl.isSuspended(processContainerDmc) == false) { + MIEvent event = MIStoppedEvent.parse(processContainerDmc, id, rr.getMIResults()); + fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties()); + } + } } } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIThread.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIThread.java new file mode 100644 index 00000000000..482a23887d8 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIThread.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.dsf.mi.service.command.commands; + +import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext; +import org.eclipse.cdt.dsf.mi.service.command.output.CLIThreadInfo; +import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput; + +/** + * + * thread + * + * [Current thread is 1 (Thread 0xb7cc56b0 (LWP 5488))] + * + * @since 3.0 + * + */ +public class CLIThread extends CLICommand { + + public CLIThread(IContainerDMContext ctx) { + super(ctx, "thread"); //$NON-NLS-1$ + } + + @Override + public CLIThreadInfo getResult(MIOutput output) { + return new CLIThreadInfo(output); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/CLIThreadInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/CLIThreadInfo.java new file mode 100644 index 00000000000..1cd2a27ec01 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/CLIThreadInfo.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.dsf.mi.service.command.output; + + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +/** + * [Current thread is 1 (Thread 0xb7cc56b0 (LWP 5488))] + * + * @since 3.0 + */ +public class CLIThreadInfo extends MIInfo { + + private Integer fCurrentThread; + + public CLIThreadInfo(MIOutput out) { + super(out); + parse(); + } + + public Integer getCurrentThread(){ + return fCurrentThread; + } + + protected void parse() { + if (isDone()) { + MIOutput out = getMIOutput(); + MIOOBRecord[] oobs = out.getMIOOBRecords(); + for (int i = 0; i < oobs.length; i++) { + if (oobs[i] instanceof MIConsoleStreamOutput) { + MIStreamRecord cons = (MIStreamRecord) oobs[i]; + String str = cons.getString(); + // We are interested in finding the current thread + parseThreadInfo(str.trim()); + } + } + } + } + + protected void parseThreadInfo(String str) { + // Fetch the OS ThreadId & Find the current thread + if(str.length() > 0 ){ + Pattern pattern = Pattern.compile("Current thread is (\\d+)", Pattern.MULTILINE); //$NON-NLS-1$ + Matcher matcher = pattern.matcher(str); + if (matcher.find()) { + String id = matcher.group(1).trim(); + fCurrentThread = Integer.parseInt(id); + } + } + } +}