mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-22 06:02:11 +02:00
Buf fix in MIInferior.
This commit is contained in:
parent
1c66d960ea
commit
fa183e80b0
6 changed files with 242 additions and 182 deletions
|
@ -10,8 +10,8 @@ import java.io.IOException;
|
||||||
import org.eclipse.cdt.debug.mi.core.event.MIEvent;
|
import org.eclipse.cdt.debug.mi.core.event.MIEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transmission command thread blocks on the command Queue
|
* Event Thread blocks on the event Queue, wakes up
|
||||||
* and wake cmd are available and push them to gdb out channel.
|
* when events are available and notify all the observers.
|
||||||
*/
|
*/
|
||||||
public class EventThread extends Thread {
|
public class EventThread extends Thread {
|
||||||
|
|
||||||
|
@ -22,29 +22,24 @@ public class EventThread extends Thread {
|
||||||
session = s;
|
session = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run () {
|
public void run() {
|
||||||
try {
|
// signal by the session of time to die.
|
||||||
while (true) {
|
while (session.getChannelOutputStream() != null) {
|
||||||
MIEvent event = null;
|
MIEvent event = null;
|
||||||
Queue eventQueue = session.getEventQueue();
|
Queue eventQueue = session.getEventQueue();
|
||||||
// removeItem() will block until an item is available.
|
// removeItem() will block until an item is available.
|
||||||
try {
|
try {
|
||||||
event = (MIEvent)eventQueue.removeItem();
|
event = (MIEvent) eventQueue.removeItem();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// signal by the session of time to die.
|
//e.printStackTrace();
|
||||||
if (session.getChannelOutputStream() == null) {
|
}
|
||||||
throw new IOException();
|
try {
|
||||||
}
|
if (event != null) {
|
||||||
//e.printStackTrace();
|
session.notifyObservers(event);
|
||||||
}
|
}
|
||||||
try {
|
} catch (Exception e) {
|
||||||
session.notifyObservers(event);
|
e.printStackTrace();
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
|
||||||
//e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,65 +3,71 @@ package org.eclipse.cdt.debug.mi.core;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.io.PipedInputStream;
|
||||||
|
import java.io.PipedOutputStream;
|
||||||
|
|
||||||
import org.eclipse.cdt.debug.mi.core.command.CLICommand;
|
import org.eclipse.cdt.debug.mi.core.command.CLICommand;
|
||||||
import org.eclipse.cdt.debug.mi.core.command.CommandFactory;
|
import org.eclipse.cdt.debug.mi.core.command.CommandFactory;
|
||||||
import org.eclipse.cdt.debug.mi.core.command.MIExecAbort;
|
import org.eclipse.cdt.debug.mi.core.command.MIExecAbort;
|
||||||
import org.eclipse.cdt.debug.mi.core.command.MIGDBExit;
|
|
||||||
import org.eclipse.cdt.debug.mi.core.command.MIGDBShowExitCode;
|
import org.eclipse.cdt.debug.mi.core.command.MIGDBShowExitCode;
|
||||||
import org.eclipse.cdt.debug.mi.core.event.MIExitEvent;
|
|
||||||
import org.eclipse.cdt.debug.mi.core.event.MIInferiorExitEvent;
|
import org.eclipse.cdt.debug.mi.core.event.MIInferiorExitEvent;
|
||||||
import org.eclipse.cdt.debug.mi.core.output.MIGDBShowExitCodeInfo;
|
import org.eclipse.cdt.debug.mi.core.output.MIGDBShowExitCodeInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author alain
|
|
||||||
*
|
|
||||||
* To change this generated comment edit the template variable "typecomment":
|
|
||||||
* Window>Preferences>Java>Templates.
|
|
||||||
* To enable and disable the creation of type comments go to
|
|
||||||
* Window>Preferences>Java>Code Generation.
|
|
||||||
*/
|
*/
|
||||||
public class MIInferior extends Process {
|
public class MIInferior extends Process {
|
||||||
|
|
||||||
public final static int SUSPENDED = 1;
|
final static int SUSPENDED = 1;
|
||||||
public final static int RUNNING = 2;
|
final static int RUNNING = 2;
|
||||||
public final static int TERMINATED = 4;
|
final static int TERMINATED = 4;
|
||||||
|
|
||||||
|
boolean connected = false;
|
||||||
|
|
||||||
int state = 0;
|
int state = 0;
|
||||||
|
|
||||||
MISession session;
|
MISession session;
|
||||||
|
|
||||||
OutputStream out;
|
OutputStream out;
|
||||||
|
|
||||||
|
PipedInputStream in;
|
||||||
|
PipedOutputStream inPiped;
|
||||||
|
|
||||||
|
PipedInputStream err;
|
||||||
|
PipedOutputStream errPiped;
|
||||||
|
|
||||||
MIInferior(MISession mi) {
|
MIInferior(MISession mi) {
|
||||||
session = mi;
|
session = mi;
|
||||||
out = new OutputStream() {
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
public void write(int b) throws IOException {
|
|
||||||
buf.append(b);
|
|
||||||
if (b == '\n') {
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Encapsulate the string sent to gdb in a fake command.
|
|
||||||
// and post it to the TxThread.
|
|
||||||
public void flush() throws IOException {
|
|
||||||
CLICommand cmd = new CLICommand(buf.toString()) {
|
|
||||||
public void setToken(int token) {
|
|
||||||
// override to do nothing;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
session.postCommand(cmd);
|
|
||||||
} catch (MIException e) {
|
|
||||||
throw new IOException("no mi session");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see java.lang.Process#getOutputStream()
|
* @see java.lang.Process#getOutputStream()
|
||||||
*/
|
*/
|
||||||
public OutputStream getOutputStream() {
|
public OutputStream getOutputStream() {
|
||||||
|
if (out == null) {
|
||||||
|
out = new OutputStream() {
|
||||||
|
StringBuffer buf = new StringBuffer();
|
||||||
|
public void write(int b) throws IOException {
|
||||||
|
buf.append(b);
|
||||||
|
if (b == '\n') {
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Encapsulate the string sent to gdb in a fake command.
|
||||||
|
// and post it to the TxThread.
|
||||||
|
public void flush() throws IOException {
|
||||||
|
CLICommand cmd = new CLICommand(buf.toString()) {
|
||||||
|
public void setToken(int token) {
|
||||||
|
// override to do nothing;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
session.postCommand(cmd);
|
||||||
|
} catch (MIException e) {
|
||||||
|
throw new IOException("no mi session");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,15 +75,30 @@ public class MIInferior extends Process {
|
||||||
* @see java.lang.Process#getInputStream()
|
* @see java.lang.Process#getInputStream()
|
||||||
*/
|
*/
|
||||||
public InputStream getInputStream() {
|
public InputStream getInputStream() {
|
||||||
return session.getTargetStream();
|
if (in == null) {
|
||||||
|
try {
|
||||||
|
inPiped = new PipedOutputStream();
|
||||||
|
in = new PipedInputStream(inPiped);
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see java.lang.Process#getErrorStream()
|
* @see java.lang.Process#getErrorStream()
|
||||||
*/
|
*/
|
||||||
public InputStream getErrorStream() {
|
public InputStream getErrorStream() {
|
||||||
// FIXME the same as output??
|
// FIXME: We do not have any err stream from gdb/mi
|
||||||
return session.getTargetStream();
|
// so this gdb err channel instead.
|
||||||
|
if (err == null) {
|
||||||
|
try {
|
||||||
|
errPiped = new PipedOutputStream();
|
||||||
|
err = new PipedInputStream(errPiped);
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -96,7 +117,7 @@ public class MIInferior extends Process {
|
||||||
* @see java.lang.Process#exitValue()
|
* @see java.lang.Process#exitValue()
|
||||||
*/
|
*/
|
||||||
public int exitValue() {
|
public int exitValue() {
|
||||||
if (isTerminated()) {
|
if (isTerminated() && !session.isTerminated()) {
|
||||||
CommandFactory factory = session.getCommandFactory();
|
CommandFactory factory = session.getCommandFactory();
|
||||||
MIGDBShowExitCode code = factory.createMIGDBShowExitCode();
|
MIGDBShowExitCode code = factory.createMIGDBShowExitCode();
|
||||||
try {
|
try {
|
||||||
|
@ -114,29 +135,15 @@ public class MIInferior extends Process {
|
||||||
* @see java.lang.Process#destroy()
|
* @see java.lang.Process#destroy()
|
||||||
*/
|
*/
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
/*
|
|
||||||
if (!isTerminated()) {
|
if (!isTerminated()) {
|
||||||
CommandFactory factory = session.getCommandFactory();
|
CommandFactory factory = session.getCommandFactory();
|
||||||
MIExecAbort abort = factory.createMIExecAbort();
|
MIExecAbort abort = factory.createMIExecAbort();
|
||||||
try {
|
try {
|
||||||
session.postCommand(abort);
|
session.postCommand(abort);
|
||||||
setTerminated();
|
|
||||||
session.getRxThread().fireEvent(new MIInferiorExitEvent());
|
session.getRxThread().fireEvent(new MIInferiorExitEvent());
|
||||||
} catch (MIException e) {
|
} catch (MIException e) {
|
||||||
}
|
}
|
||||||
}
|
setTerminated();
|
||||||
*/
|
|
||||||
if (!isTerminated()) {
|
|
||||||
if (!isSuspended())
|
|
||||||
{
|
|
||||||
// interrupt execution
|
|
||||||
}
|
|
||||||
CommandFactory factory = session.getCommandFactory();
|
|
||||||
MIGDBExit exit = factory.createMIGDBExit();
|
|
||||||
try {
|
|
||||||
session.postCommand(exit);
|
|
||||||
} catch (MIException e) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,6 +159,18 @@ public class MIInferior extends Process {
|
||||||
return state == TERMINATED;
|
return state == TERMINATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isConnected() {
|
||||||
|
return connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void setConnected() {
|
||||||
|
connected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void setDisConnected() {
|
||||||
|
connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void setSuspended() {
|
public synchronized void setSuspended() {
|
||||||
state = SUSPENDED;
|
state = SUSPENDED;
|
||||||
}
|
}
|
||||||
|
@ -162,6 +181,31 @@ public class MIInferior extends Process {
|
||||||
|
|
||||||
public synchronized void setTerminated() {
|
public synchronized void setTerminated() {
|
||||||
state = TERMINATED;
|
state = TERMINATED;
|
||||||
|
// Close the streams.
|
||||||
|
try {
|
||||||
|
if (inPiped != null) {
|
||||||
|
inPiped.close();
|
||||||
|
inPiped = null;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (errPiped != null) {
|
||||||
|
errPiped.close();
|
||||||
|
errPiped = null;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
notifyAll();
|
notifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public OutputStream getPipedOutputStream() {
|
||||||
|
return inPiped;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OutputStream getPipedErrorStream() {
|
||||||
|
return errPiped;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,10 +51,10 @@ public class MIPlugin extends Plugin {
|
||||||
String[]args = new String[]{"gdb", "-q", "-i", "mi", program};
|
String[]args = new String[]{"gdb", "-q", "-i", "mi", program};
|
||||||
Process gdb = Runtime.getRuntime().exec(args);
|
Process gdb = Runtime.getRuntime().exec(args);
|
||||||
MISession session = createMISession(gdb.getInputStream(), gdb.getOutputStream());
|
MISession session = createMISession(gdb.getInputStream(), gdb.getOutputStream());
|
||||||
/*
|
///*
|
||||||
try {
|
try {
|
||||||
CommandFactory factory = session.getCommandFactory();
|
CommandFactory factory = session.getCommandFactory();
|
||||||
MIBreakInsert bkpt= factory.createMIBreakInsert(true, false, null, 0, "main");
|
MIBreakInsert bkpt= factory.createMIBreakInsert(true, false, null, 0, "routine");
|
||||||
session.postCommand(bkpt);
|
session.postCommand(bkpt);
|
||||||
MIInfo info = bkpt.getMIInfo();
|
MIInfo info = bkpt.getMIInfo();
|
||||||
if (info == null) {
|
if (info == null) {
|
||||||
|
@ -63,7 +63,7 @@ public class MIPlugin extends Plugin {
|
||||||
} catch (MIException e) {
|
} catch (MIException e) {
|
||||||
throw new IOException("Failed to attach");
|
throw new IOException("Failed to attach");
|
||||||
}
|
}
|
||||||
*/
|
//*/
|
||||||
return new CSession(session);
|
return new CSession(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.eclipse.cdt.debug.mi.core.command.Command;
|
||||||
import org.eclipse.cdt.debug.mi.core.command.CommandFactory;
|
import org.eclipse.cdt.debug.mi.core.command.CommandFactory;
|
||||||
import org.eclipse.cdt.debug.mi.core.command.MIGDBExit;
|
import org.eclipse.cdt.debug.mi.core.command.MIGDBExit;
|
||||||
import org.eclipse.cdt.debug.mi.core.command.MIGDBSet;
|
import org.eclipse.cdt.debug.mi.core.command.MIGDBSet;
|
||||||
|
import org.eclipse.cdt.debug.mi.core.output.MIInfo;
|
||||||
import org.eclipse.cdt.debug.mi.core.output.MIOutput;
|
import org.eclipse.cdt.debug.mi.core.output.MIOutput;
|
||||||
import org.eclipse.cdt.debug.mi.core.output.MIParser;
|
import org.eclipse.cdt.debug.mi.core.output.MIParser;
|
||||||
|
|
||||||
|
@ -39,10 +40,6 @@ public class MISession extends Observable {
|
||||||
|
|
||||||
PipedInputStream miInPipe;
|
PipedInputStream miInPipe;
|
||||||
PipedOutputStream miOutPipe;
|
PipedOutputStream miOutPipe;
|
||||||
PipedInputStream targetInPipe;
|
|
||||||
PipedOutputStream targetOutPipe;
|
|
||||||
PipedInputStream logInPipe;
|
|
||||||
PipedOutputStream logOutPipe;
|
|
||||||
|
|
||||||
CommandFactory factory;
|
CommandFactory factory;
|
||||||
|
|
||||||
|
@ -61,59 +58,62 @@ public class MISession extends Observable {
|
||||||
public MISession(InputStream i, OutputStream o) {
|
public MISession(InputStream i, OutputStream o) {
|
||||||
inChannel = i;
|
inChannel = i;
|
||||||
outChannel = o;
|
outChannel = o;
|
||||||
|
|
||||||
factory = new CommandFactory();
|
factory = new CommandFactory();
|
||||||
|
|
||||||
parser = new MIParser();
|
parser = new MIParser();
|
||||||
|
|
||||||
txQueue = new CommandQueue();
|
txQueue = new CommandQueue();
|
||||||
rxQueue = new CommandQueue();
|
rxQueue = new CommandQueue();
|
||||||
eventQueue = new Queue();
|
eventQueue = new Queue();
|
||||||
|
|
||||||
txThread = new TxThread(this);
|
txThread = new TxThread(this);
|
||||||
rxThread = new RxThread(this);
|
rxThread = new RxThread(this);
|
||||||
eventThread = new EventThread(this);
|
eventThread = new EventThread(this);
|
||||||
|
|
||||||
txThread.start();
|
txThread.start();
|
||||||
rxThread.start();
|
rxThread.start();
|
||||||
eventThread.start();
|
eventThread.start();
|
||||||
|
|
||||||
try {
|
|
||||||
miOutPipe = new PipedOutputStream();
|
|
||||||
miInPipe = new PipedInputStream(miOutPipe);
|
|
||||||
targetOutPipe = new PipedOutputStream();
|
|
||||||
targetInPipe = new PipedInputStream(targetOutPipe);
|
|
||||||
logOutPipe = new PipedOutputStream();
|
|
||||||
logInPipe = new PipedInputStream(logOutPipe);
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
inferior = new MIInferior(this);
|
inferior = new MIInferior(this);
|
||||||
try {
|
try {
|
||||||
postCommand(new MIGDBSet(new String[]{"confirm", "off"}));
|
// Disable a certain number of irritations from gdb.
|
||||||
|
// Like confirmation and screen size.
|
||||||
|
MIInfo info;
|
||||||
|
|
||||||
|
MIGDBSet confirm = new MIGDBSet(new String[]{"confirm", "off"});
|
||||||
|
postCommand(confirm);
|
||||||
|
info = confirm.getMIInfo();
|
||||||
|
|
||||||
|
MIGDBSet width = new MIGDBSet(new String[]{"width", "99999999"});
|
||||||
|
postCommand(width);
|
||||||
|
info = confirm.getMIInfo();
|
||||||
|
|
||||||
|
MIGDBSet height = new MIGDBSet(new String[]{"height", "99999999"});
|
||||||
|
postCommand(height);
|
||||||
|
info = confirm.getMIInfo();
|
||||||
} catch (MIException e) {
|
} catch (MIException e) {
|
||||||
|
// FIXME: Do not catch the exception but pass it up.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get Console Stream.
|
* get MI Console Stream.
|
||||||
*/
|
*/
|
||||||
public InputStream getMIStream() {
|
public InputStream getMIStream() {
|
||||||
|
if (miInPipe == null) {
|
||||||
|
try {
|
||||||
|
miOutPipe = new PipedOutputStream();
|
||||||
|
miInPipe = new PipedInputStream(miOutPipe);
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
return miInPipe;
|
return miInPipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Target Stream.
|
* For example the CDI/MI bridge uses the command
|
||||||
*/
|
|
||||||
public InputStream getTargetStream() {
|
|
||||||
return targetInPipe;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Log Stream
|
|
||||||
*/
|
|
||||||
public InputStream getLogStream() {
|
|
||||||
return logInPipe;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For example the CDI/MI adapters uses the command
|
|
||||||
* factory to create MI commands this allow overloading.
|
* factory to create MI commands this allow overloading.
|
||||||
*/
|
*/
|
||||||
public CommandFactory getCommandFactory() {
|
public CommandFactory getCommandFactory() {
|
||||||
|
@ -121,21 +121,21 @@ public class MISession extends Observable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a new factory to use in CDI/MI adapters.
|
* Set a new factory to use for command.
|
||||||
*/
|
*/
|
||||||
public void setCommandFactory(CommandFactory f) {
|
public void setCommandFactory(CommandFactory f) {
|
||||||
factory = f;
|
factory = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the MI main parser.
|
* Return the MI parser.
|
||||||
*/
|
*/
|
||||||
public MIParser getMIParser() {
|
public MIParser getMIParser() {
|
||||||
return parser;
|
return parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the parser.
|
* Reset the MI parser.
|
||||||
*/
|
*/
|
||||||
public void setMIParser(MIParser p) {
|
public void setMIParser(MIParser p) {
|
||||||
parser = p;
|
parser = p;
|
||||||
|
@ -156,6 +156,7 @@ public class MISession extends Observable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* equivalent to:
|
||||||
* postCommand(cmd, 10 secs)
|
* postCommand(cmd, 10 secs)
|
||||||
*/
|
*/
|
||||||
public void postCommand(Command cmd) throws MIException {
|
public void postCommand(Command cmd) throws MIException {
|
||||||
|
@ -163,13 +164,14 @@ public class MISession extends Observable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a command to gdb.
|
* Sends a command to gdb, and wait(timeout) for a response.
|
||||||
*/
|
*/
|
||||||
public void postCommand(Command cmd, long timeout) throws MIException {
|
static int number = 1;
|
||||||
|
public synchronized void postCommand(Command cmd, long timeout) throws MIException {
|
||||||
|
|
||||||
MIPlugin.getDefault().debugLog(cmd.toString());
|
MIPlugin.getDefault().debugLog(number++ + " " + cmd.toString());
|
||||||
|
|
||||||
// Test if we in a sane state.
|
// Test if we are in a sane state.
|
||||||
if (!txThread.isAlive() || !rxThread.isAlive()) {
|
if (!txThread.isAlive() || !rxThread.isAlive()) {
|
||||||
throw new MIException("{R,T}xThread terminated");
|
throw new MIException("{R,T}xThread terminated");
|
||||||
}
|
}
|
||||||
|
@ -178,53 +180,57 @@ public class MISession extends Observable {
|
||||||
|
|
||||||
// Wait for the response or timedout
|
// Wait for the response or timedout
|
||||||
synchronized (cmd) {
|
synchronized (cmd) {
|
||||||
// Do not wait for command if time out is 0
|
// RxThread will set the MIOutput on the cmd
|
||||||
if (timeout > 0) {
|
// when the response arrive.
|
||||||
// RxThread will set the MIOutput on the cmd
|
while (cmd.getMIOutput() == null) {
|
||||||
// when the response arrive.
|
try {
|
||||||
while (cmd.getMIOutput() == null) {
|
cmd.wait(timeout);
|
||||||
try {
|
if (cmd.getMIOutput() == null) {
|
||||||
cmd.wait(timeout);
|
throw new MIException("Timedout");
|
||||||
if (cmd.getMIOutput() == null) {
|
|
||||||
throw new MIException("Timedout");
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
}
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the inferior "Process".
|
||||||
|
*/
|
||||||
public MIInferior getMIInferior() {
|
public MIInferior getMIInferior() {
|
||||||
return inferior;
|
return inferior;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the gdb session is terminated.
|
||||||
|
*/
|
||||||
public boolean isTerminated() {
|
public boolean isTerminated() {
|
||||||
return (!txThread.isAlive() || !rxThread.isAlive());
|
return (!txThread.isAlive() || !rxThread.isAlive());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the MISession.
|
* Terminate the MISession.
|
||||||
*/
|
*/
|
||||||
public void terminate() {
|
public void terminate() {
|
||||||
|
|
||||||
// Destroy any MI Inferior
|
// Destroy any MI Inferior(Process)
|
||||||
inferior.destroy();
|
inferior.destroy();
|
||||||
|
|
||||||
// send the exit.
|
// send the exit(-gdb-exit).
|
||||||
try {
|
try {
|
||||||
MIGDBExit exit = factory.createMIGDBExit();
|
MIGDBExit exit = factory.createMIGDBExit();
|
||||||
postCommand(exit);
|
postCommand(exit);
|
||||||
} catch (MIException e) {
|
} catch (MIException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explicitely close the channels
|
// Close the input GDB prompt
|
||||||
try {
|
try {
|
||||||
inChannel.close();
|
inChannel.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
}
|
}
|
||||||
inChannel = null;
|
inChannel = null;
|
||||||
|
|
||||||
|
// Close the output GDB prompt
|
||||||
try {
|
try {
|
||||||
outChannel.close();
|
outChannel.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -232,30 +238,39 @@ public class MISession extends Observable {
|
||||||
// This is __needed__ to stop the txThread and eventThread.
|
// This is __needed__ to stop the txThread and eventThread.
|
||||||
outChannel = null;
|
outChannel = null;
|
||||||
|
|
||||||
// Make sure all threads are gone.
|
// Kill the Transmition thread.
|
||||||
try {
|
try {
|
||||||
if (txThread.isAlive()) {
|
if (txThread.isAlive()) {
|
||||||
txThread.interrupt();
|
txThread.interrupt();
|
||||||
}
|
}
|
||||||
txThread.join();
|
txThread.join(cmdTimeout);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Kill the Receiving Thread.
|
||||||
try {
|
try {
|
||||||
if (rxThread.isAlive()) {
|
if (rxThread.isAlive()) {
|
||||||
rxThread.interrupt();
|
rxThread.interrupt();
|
||||||
}
|
}
|
||||||
rxThread.join();
|
rxThread.join(cmdTimeout);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Kill the event Thread.
|
||||||
try {
|
try {
|
||||||
if (eventThread.isAlive()) {
|
if (eventThread.isAlive()) {
|
||||||
eventThread.interrupt();
|
eventThread.interrupt();
|
||||||
}
|
}
|
||||||
eventThread.join();
|
eventThread.join(cmdTimeout);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Destroy the MI console stream.
|
||||||
|
try {
|
||||||
|
miOutPipe.close();
|
||||||
|
miInPipe = null;
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -271,14 +286,6 @@ public class MISession extends Observable {
|
||||||
return miOutPipe;
|
return miOutPipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputStream getTargetPipe() {
|
|
||||||
return targetOutPipe;
|
|
||||||
}
|
|
||||||
|
|
||||||
OutputStream getLogPipe() {
|
|
||||||
return logOutPipe;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandQueue getTxQueue() {
|
CommandQueue getTxQueue() {
|
||||||
return txQueue;
|
return txQueue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,15 +44,17 @@ import org.eclipse.cdt.debug.mi.core.output.MITargetStreamOutput;
|
||||||
import org.eclipse.cdt.debug.mi.core.output.MIValue;
|
import org.eclipse.cdt.debug.mi.core.output.MIValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receiving thread of gdb, read the input channel.
|
* Receiving thread of gdb response output.
|
||||||
*/
|
*/
|
||||||
public class RxThread extends Thread {
|
public class RxThread extends Thread {
|
||||||
|
|
||||||
final MISession session;
|
final MISession session;
|
||||||
|
List oobList;
|
||||||
|
|
||||||
public RxThread(MISession s) {
|
public RxThread(MISession s) {
|
||||||
super("MI RX Thread");
|
super("MI RX Thread");
|
||||||
session = s;
|
session = s;
|
||||||
|
oobList = new ArrayList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -62,7 +64,6 @@ public class RxThread extends Thread {
|
||||||
public void run () {
|
public void run () {
|
||||||
BufferedReader reader =
|
BufferedReader reader =
|
||||||
new BufferedReader(new InputStreamReader(session.getChannelInputStream()));
|
new BufferedReader(new InputStreamReader(session.getChannelInputStream()));
|
||||||
StringBuffer buffer = new StringBuffer();
|
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
String line;
|
String line;
|
||||||
|
@ -121,20 +122,33 @@ MIPlugin.getDefault().debugLog(line);
|
||||||
fireEvent(event);
|
fireEvent(event);
|
||||||
} else if ("exit".equals(state)) {
|
} else if ("exit".equals(state)) {
|
||||||
session.getMIInferior().setTerminated();
|
session.getMIInferior().setTerminated();
|
||||||
fireEvent(new MIExitEvent());
|
MIEvent event = new MIExitEvent();
|
||||||
|
fireEvent(event);
|
||||||
|
} else if ("connected".equals(state)) {
|
||||||
|
session.getMIInferior().setConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear the accumulate oobList on each new Result Command
|
||||||
|
// response.
|
||||||
|
MIOOBRecord [] oobRecords =
|
||||||
|
(MIOOBRecord[])oobList.toArray(new MIOOBRecord[0]);
|
||||||
|
oobList.clear();
|
||||||
|
|
||||||
// Notify the waiting command.
|
// Notify the waiting command.
|
||||||
if (cmd != null) {
|
if (cmd != null) {
|
||||||
synchronized (cmd) {
|
synchronized (cmd) {
|
||||||
|
// Set the accumulate console Stream
|
||||||
|
response.setMIOOBRecords(oobRecords);
|
||||||
cmd.setMIOutput(response);
|
cmd.setMIOutput(response);
|
||||||
cmd.notifyAll();
|
cmd.notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some result record contains informaton specific to oob.
|
// Some result record contains informaton specific to oob.
|
||||||
// This will happen when CLI-Command is use, for example
|
// This will happen when CLI-Command is use, for example
|
||||||
// doing "run" will block and return a breakpointhit
|
// doing "run" will block and return a breakpointhit
|
||||||
processMIOOBRecord(rr, list);
|
processMIOOBRecord(rr, list);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process OOBs
|
// Process OOBs
|
||||||
|
@ -162,35 +176,33 @@ MIPlugin.getDefault().debugLog(line);
|
||||||
void processMIOOBRecord(MIAsyncRecord async, List list) {
|
void processMIOOBRecord(MIAsyncRecord async, List list) {
|
||||||
if (async instanceof MIExecAsyncOutput) {
|
if (async instanceof MIExecAsyncOutput) {
|
||||||
MIExecAsyncOutput exec = (MIExecAsyncOutput)async;
|
MIExecAsyncOutput exec = (MIExecAsyncOutput)async;
|
||||||
MIEvent e = null;
|
|
||||||
|
|
||||||
// Change of state.
|
// Change of state.
|
||||||
String state = exec.getAsyncClass();
|
String state = exec.getAsyncClass();
|
||||||
if ("stopped".equals(state)) {
|
if ("stopped".equals(state)) {
|
||||||
|
MIEvent e = null;
|
||||||
session.getMIInferior().setSuspended();
|
session.getMIInferior().setSuspended();
|
||||||
}
|
MIResult[] results = exec.getMIResults();
|
||||||
|
for (int i = 0; i < results.length; i++) {
|
||||||
MIResult[] results = exec.getMIResults();
|
String var = results[i].getVariable();
|
||||||
for (int i = 0; i < results.length; i++) {
|
MIValue val = results[i].getMIValue();
|
||||||
String var = results[i].getVariable();
|
if (var.equals("reason")) {
|
||||||
MIValue val = results[i].getMIValue();
|
if (val instanceof MIConst) {
|
||||||
if (var.equals("reason")) {
|
String reason =((MIConst)val).getString();
|
||||||
if (val instanceof MIConst) {
|
e = createEvent(reason, exec);
|
||||||
String reason = ((MIConst)val).getString();
|
if (e != null) {
|
||||||
e = createEvent(reason, exec);
|
list.add(e);
|
||||||
if (e != null) {
|
}
|
||||||
list.add(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// HACK: GDB for temporary breakpoints will not send the
|
// HACK: GDB for temporary breakpoints will not send the
|
||||||
// "reason" ??? Fake this as breakpoint-hit
|
// "reason" ??? Fake this as breakpoint-hit
|
||||||
if (e == null) {
|
if (e == null) {
|
||||||
e = createEvent("breakpoint-hit", exec);
|
e = createEvent("breakpoint-hit", exec);
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
list.add(e);
|
list.add(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (async instanceof MIStatusAsyncOutput) {
|
} else if (async instanceof MIStatusAsyncOutput) {
|
||||||
|
@ -214,8 +226,11 @@ MIPlugin.getDefault().debugLog(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Accumulate the Console Stream Output response for parsing.
|
||||||
|
// Some commands will put valuable info in the Console Stream.
|
||||||
|
oobList.add(stream);
|
||||||
} else if (stream instanceof MITargetStreamOutput) {
|
} else if (stream instanceof MITargetStreamOutput) {
|
||||||
OutputStream target = session.getTargetPipe();
|
OutputStream target = session.getMIInferior().getPipedOutputStream();
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
MITargetStreamOutput out = (MITargetStreamOutput)stream;
|
MITargetStreamOutput out = (MITargetStreamOutput)stream;
|
||||||
String str = out.getString();
|
String str = out.getString();
|
||||||
|
@ -228,7 +243,7 @@ MIPlugin.getDefault().debugLog(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (stream instanceof MILogStreamOutput) {
|
} else if (stream instanceof MILogStreamOutput) {
|
||||||
OutputStream log = session.getLogPipe();
|
OutputStream log = session.getMIInferior().getPipedErrorStream();
|
||||||
if (log != null) {
|
if (log != null) {
|
||||||
MILogStreamOutput out = (MILogStreamOutput)stream;
|
MILogStreamOutput out = (MILogStreamOutput)stream;
|
||||||
String str = out.getString();
|
String str = out.getString();
|
||||||
|
@ -310,13 +325,13 @@ MIPlugin.getDefault().debugLog(line);
|
||||||
event = new MIFunctionFinishedEvent(rr);
|
event = new MIFunctionFinishedEvent(rr);
|
||||||
}
|
}
|
||||||
} else if ("exited-normally".equals(reason)) {
|
} else if ("exited-normally".equals(reason)) {
|
||||||
// session.getMIInferior().setTerminated();
|
session.getMIInferior().setTerminated();
|
||||||
event = new MIInferiorExitEvent();
|
event = new MIInferiorExitEvent();
|
||||||
} else if ("exited-signalled".equals(reason)) {
|
} else if ("exited-signalled".equals(reason)) {
|
||||||
// session.getMIInferior().setTerminated();
|
session.getMIInferior().setTerminated();
|
||||||
event = new MIInferiorExitEvent();
|
event = new MIInferiorExitEvent();
|
||||||
} else if ("exited".equals(reason)) {
|
} else if ("exited".equals(reason)) {
|
||||||
// session.getMIInferior().setTerminated();
|
session.getMIInferior().setTerminated();
|
||||||
event = new MIInferiorExitEvent();
|
event = new MIInferiorExitEvent();
|
||||||
}
|
}
|
||||||
return event;
|
return event;
|
||||||
|
|
|
@ -28,17 +28,14 @@ public class TxThread extends Thread {
|
||||||
|
|
||||||
public void run () {
|
public void run () {
|
||||||
try {
|
try {
|
||||||
while (true) {
|
// signal by the session of time to die.
|
||||||
|
while (session.getChannelOutputStream() != null) {
|
||||||
Command cmd = null;
|
Command cmd = null;
|
||||||
CommandQueue txQueue = session.getTxQueue();
|
CommandQueue txQueue = session.getTxQueue();
|
||||||
// removeCommand() will block until a command is available.
|
// removeCommand() will block until a command is available.
|
||||||
try {
|
try {
|
||||||
cmd = txQueue.removeCommand();
|
cmd = txQueue.removeCommand();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// signal by the session of time to die.
|
|
||||||
if (session.getChannelOutputStream() == null) {
|
|
||||||
throw new IOException();
|
|
||||||
}
|
|
||||||
//e.printStackTrace();
|
//e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,8 +52,10 @@ public class TxThread extends Thread {
|
||||||
// shove in the pipe
|
// shove in the pipe
|
||||||
String str = cmd.toString();
|
String str = cmd.toString();
|
||||||
OutputStream out = session.getChannelOutputStream();
|
OutputStream out = session.getChannelOutputStream();
|
||||||
out.write(str.getBytes());
|
if (out != null) {
|
||||||
out.flush();
|
out.write(str.getBytes());
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue