forked from qt-creator/qt-creator
Debugger: Rework 'Attach to unstarted application' startup
Change-Id: I42c7ce8e413c850e05b02f5d6fe1b83376436c65 Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
This commit is contained in:
@@ -487,7 +487,7 @@ AttachToQmlPortDialog::AttachToQmlPortDialog(QWidget *parent)
|
|||||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
setWindowTitle(tr("Start Debugger"));
|
setWindowTitle(tr("Start Debugger"));
|
||||||
|
|
||||||
d->kitChooser = new DebuggerKitChooser(DebuggerKitChooser::RemoteDebugging, this);
|
d->kitChooser = new DebuggerKitChooser(DebuggerKitChooser::AnyDebugging, this);
|
||||||
d->kitChooser->populate();
|
d->kitChooser->populate();
|
||||||
|
|
||||||
d->portSpinBox = new QSpinBox(this);
|
d->portSpinBox = new QSpinBox(this);
|
||||||
|
@@ -59,12 +59,14 @@ class StartApplicationParameters;
|
|||||||
class StartApplicationDialogPrivate;
|
class StartApplicationDialogPrivate;
|
||||||
class StartRemoteEngineDialogPrivate;
|
class StartRemoteEngineDialogPrivate;
|
||||||
|
|
||||||
class DebuggerKitChooser : public ProjectExplorer::KitChooser {
|
class DebuggerKitChooser : public ProjectExplorer::KitChooser
|
||||||
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
|
||||||
enum Mode { RemoteDebugging, LocalDebugging };
|
|
||||||
|
|
||||||
explicit DebuggerKitChooser(Mode mode = RemoteDebugging, QWidget *parent = 0);
|
public:
|
||||||
|
enum Mode { AnyDebugging, LocalDebugging };
|
||||||
|
|
||||||
|
explicit DebuggerKitChooser(Mode mode = AnyDebugging, QWidget *parent = 0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool kitMatches(const ProjectExplorer::Kit *k) const;
|
bool kitMatches(const ProjectExplorer::Kit *k) const;
|
||||||
|
@@ -612,7 +612,8 @@ public:
|
|||||||
m_threadBox->setCurrentIndex(index);
|
m_threadBox->setCurrentIndex(index);
|
||||||
m_threadBox->blockSignals(state);
|
m_threadBox->blockSignals(state);
|
||||||
}
|
}
|
||||||
DebuggerRunControl *attachToRunningProcess(Kit *kit, DeviceProcessItem process);
|
|
||||||
|
DebuggerRunControl *attachToRunningProcess(Kit *kit, DeviceProcessItem process, bool contAfterAttach);
|
||||||
|
|
||||||
void writeSettings()
|
void writeSettings()
|
||||||
{
|
{
|
||||||
@@ -710,13 +711,10 @@ public:
|
|||||||
|
|
||||||
void startAndDebugApplication();
|
void startAndDebugApplication();
|
||||||
void startRemoteCdbSession();
|
void startRemoteCdbSession();
|
||||||
void startRemoteServer();
|
void startRemoteServerAndAttachToProcess();
|
||||||
void attachToRemoteServer();
|
void attachToRemoteServer();
|
||||||
void attachToProcess(bool startServerOnly);
|
|
||||||
void attachToRunningApplication();
|
void attachToRunningApplication();
|
||||||
void attachToUnstartedApplicationDialog();
|
void attachToUnstartedApplicationDialog();
|
||||||
void attachToFoundProcess();
|
|
||||||
void continueOnAttach(Debugger::DebuggerState state);
|
|
||||||
void attachToQmlPort();
|
void attachToQmlPort();
|
||||||
Q_SLOT void runScheduled();
|
Q_SLOT void runScheduled();
|
||||||
void attachCore();
|
void attachCore();
|
||||||
@@ -1400,22 +1398,10 @@ void DebuggerPluginPrivate::attachToRemoteServer()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebuggerPluginPrivate::startRemoteServer()
|
void DebuggerPluginPrivate::startRemoteServerAndAttachToProcess()
|
||||||
{
|
{
|
||||||
attachToProcess(true);
|
auto kitChooser = new DebuggerKitChooser(DebuggerKitChooser::AnyDebugging);
|
||||||
}
|
auto dlg = new DeviceProcessesDialog(kitChooser, ICore::dialogParent());
|
||||||
|
|
||||||
void DebuggerPluginPrivate::attachToRunningApplication()
|
|
||||||
{
|
|
||||||
attachToProcess(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebuggerPluginPrivate::attachToProcess(bool startServerOnly)
|
|
||||||
{
|
|
||||||
const DebuggerKitChooser::Mode mode = startServerOnly ?
|
|
||||||
DebuggerKitChooser::RemoteDebugging : DebuggerKitChooser::LocalDebugging;
|
|
||||||
DebuggerKitChooser *kitChooser = new DebuggerKitChooser(mode);
|
|
||||||
DeviceProcessesDialog *dlg = new DeviceProcessesDialog(kitChooser, ICore::dialogParent());
|
|
||||||
dlg->addAcceptButton(DeviceProcessesDialog::tr("&Attach to Process"));
|
dlg->addAcceptButton(DeviceProcessesDialog::tr("&Attach to Process"));
|
||||||
dlg->showAllDevices();
|
dlg->showAllDevices();
|
||||||
if (dlg->exec() == QDialog::Rejected) {
|
if (dlg->exec() == QDialog::Rejected) {
|
||||||
@@ -1429,62 +1415,63 @@ void DebuggerPluginPrivate::attachToProcess(bool startServerOnly)
|
|||||||
IDevice::ConstPtr device = DeviceKitInformation::device(kit);
|
IDevice::ConstPtr device = DeviceKitInformation::device(kit);
|
||||||
QTC_ASSERT(device, return);
|
QTC_ASSERT(device, return);
|
||||||
|
|
||||||
if (device->type() != PE::DESKTOP_DEVICE_TYPE) {
|
GdbServerStarter *starter = new GdbServerStarter(dlg, true);
|
||||||
GdbServerStarter *starter = new GdbServerStarter(dlg, startServerOnly);
|
|
||||||
starter->run();
|
starter->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebuggerPluginPrivate::attachToRunningApplication()
|
||||||
|
{
|
||||||
|
auto kitChooser = new DebuggerKitChooser(DebuggerKitChooser::LocalDebugging);
|
||||||
|
|
||||||
|
auto dlg = new DeviceProcessesDialog(kitChooser, ICore::dialogParent());
|
||||||
|
dlg->addAcceptButton(DeviceProcessesDialog::tr("&Attach to Process"));
|
||||||
|
dlg->showAllDevices();
|
||||||
|
if (dlg->exec() == QDialog::Rejected) {
|
||||||
|
delete dlg;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dlg->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
Kit *kit = kitChooser->currentKit();
|
||||||
|
QTC_ASSERT(kit, return);
|
||||||
|
IDevice::ConstPtr device = DeviceKitInformation::device(kit);
|
||||||
|
QTC_ASSERT(device, return);
|
||||||
|
|
||||||
|
if (device->type() == PE::DESKTOP_DEVICE_TYPE) {
|
||||||
|
attachToRunningProcess(kit, dlg->currentProcess(), false);
|
||||||
} else {
|
} else {
|
||||||
attachToRunningProcess(kit, dlg->currentProcess());
|
GdbServerStarter *starter = new GdbServerStarter(dlg, true);
|
||||||
|
starter->run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebuggerPluginPrivate::attachToUnstartedApplicationDialog()
|
void DebuggerPluginPrivate::attachToUnstartedApplicationDialog()
|
||||||
{
|
{
|
||||||
UnstartedAppWatcherDialog *dlg = new UnstartedAppWatcherDialog(ICore::dialogParent());
|
auto dlg = new UnstartedAppWatcherDialog(ICore::dialogParent());
|
||||||
|
|
||||||
connect(dlg, &QDialog::finished, dlg, &QObject::deleteLater);
|
connect(dlg, &QDialog::finished, dlg, &QObject::deleteLater);
|
||||||
connect(dlg, &UnstartedAppWatcherDialog::processFound, this, &DebuggerPluginPrivate::attachToFoundProcess);
|
connect(dlg, &UnstartedAppWatcherDialog::processFound, this, [this, dlg] {
|
||||||
dlg->show();
|
DebuggerRunControl *rc = attachToRunningProcess(dlg->currentKit(),
|
||||||
}
|
dlg->currentProcess(),
|
||||||
|
dlg->continueOnAttach());
|
||||||
void DebuggerPluginPrivate::attachToFoundProcess()
|
|
||||||
{
|
|
||||||
UnstartedAppWatcherDialog *dlg = qobject_cast<UnstartedAppWatcherDialog *>(QObject::sender());
|
|
||||||
if (!dlg)
|
|
||||||
return;
|
|
||||||
|
|
||||||
DebuggerRunControl *rc = attachToRunningProcess(dlg->currentKit(), dlg->currentProcess());
|
|
||||||
if (!rc)
|
if (!rc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (dlg->hideOnAttach())
|
if (dlg->hideOnAttach())
|
||||||
connect(rc, &RunControl::finished, dlg, &UnstartedAppWatcherDialog::startWatching);
|
connect(rc, &RunControl::finished, dlg, &UnstartedAppWatcherDialog::startWatching);
|
||||||
|
});
|
||||||
|
|
||||||
if (dlg->continueOnAttach()) {
|
dlg->show();
|
||||||
connect(currentEngine(), &DebuggerEngine::stateChanged,
|
|
||||||
this, &DebuggerPluginPrivate::continueOnAttach);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebuggerPluginPrivate::continueOnAttach(Debugger::DebuggerState state)
|
|
||||||
{
|
|
||||||
// wait for state when we can continue
|
|
||||||
if (state != InferiorStopOk)
|
|
||||||
return;
|
|
||||||
// disconnect and continue
|
|
||||||
disconnect(currentEngine(), &DebuggerEngine::stateChanged,
|
|
||||||
this, &DebuggerPluginPrivate::continueOnAttach);
|
|
||||||
handleExecContinue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DebuggerRunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit,
|
DebuggerRunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit,
|
||||||
DeviceProcessItem process)
|
DeviceProcessItem process, bool contAfterAttach)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(kit, return 0);
|
QTC_ASSERT(kit, return 0);
|
||||||
IDevice::ConstPtr device = DeviceKitInformation::device(kit);
|
IDevice::ConstPtr device = DeviceKitInformation::device(kit);
|
||||||
QTC_ASSERT(device, return 0);
|
QTC_ASSERT(device, return 0);
|
||||||
if (process.pid == 0) {
|
if (process.pid == 0) {
|
||||||
AsynchronousMessageBox::warning(tr("Warning"),
|
AsynchronousMessageBox::warning(tr("Warning"), tr("Cannot attach to process with PID 0"));
|
||||||
tr("Cannot attach to process with PID 0"));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1512,6 +1499,7 @@ DebuggerRunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit,
|
|||||||
sp.executable = process.exe;
|
sp.executable = process.exe;
|
||||||
sp.startMode = AttachExternal;
|
sp.startMode = AttachExternal;
|
||||||
sp.closeMode = DetachAtClose;
|
sp.closeMode = DetachAtClose;
|
||||||
|
sp.continueAfterAttach = contAfterAttach;
|
||||||
return DebuggerRunControlFactory::createAndScheduleRun(sp);
|
return DebuggerRunControlFactory::createAndScheduleRun(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2648,7 +2636,7 @@ void DebuggerPluginPrivate::extensionsInitialized()
|
|||||||
|
|
||||||
act = m_startRemoteServerAction = new QAction(this);
|
act = m_startRemoteServerAction = new QAction(this);
|
||||||
act->setText(tr("Start Remote Debug Server Attached to Process..."));
|
act->setText(tr("Start Remote Debug Server Attached to Process..."));
|
||||||
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::startRemoteServer);
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::startRemoteServerAndAttachToProcess);
|
||||||
|
|
||||||
act = m_attachToRunningApplication = new QAction(this);
|
act = m_attachToRunningApplication = new QAction(this);
|
||||||
act->setText(tr("Attach to Running Application..."));
|
act->setText(tr("Attach to Running Application..."));
|
||||||
|
@@ -54,6 +54,8 @@ private:
|
|||||||
QObject *remoteCommand(const QStringList &options, const QStringList &arguments);
|
QObject *remoteCommand(const QStringList &options, const QStringList &arguments);
|
||||||
ShutdownFlag aboutToShutdown();
|
ShutdownFlag aboutToShutdown();
|
||||||
void extensionsInitialized();
|
void extensionsInitialized();
|
||||||
|
|
||||||
|
// Called from AppOutputPane::attachToRunControl().
|
||||||
Q_SLOT void attachExternalApplication(ProjectExplorer::RunControl *rc);
|
Q_SLOT void attachExternalApplication(ProjectExplorer::RunControl *rc);
|
||||||
|
|
||||||
#ifdef WITH_TESTS
|
#ifdef WITH_TESTS
|
||||||
|
@@ -89,12 +89,17 @@ void GdbAttachEngine::handleAttach(const DebuggerResponse &response)
|
|||||||
case ResultRunning:
|
case ResultRunning:
|
||||||
showMessage(_("INFERIOR ATTACHED"));
|
showMessage(_("INFERIOR ATTACHED"));
|
||||||
if (state() == EngineRunRequested) {
|
if (state() == EngineRunRequested) {
|
||||||
// FIXME: Really? Looks like we are always stopped already.
|
// Happens e.g. for "Attach to unstarted application"
|
||||||
// We will get a '*stopped' later that we'll interpret as 'spontaneous'
|
// We will get a '*stopped' later that we'll interpret as 'spontaneous'
|
||||||
// So acknowledge the current state and put a delayed 'continue' in the pipe.
|
// So acknowledge the current state and put a delayed 'continue' in the pipe.
|
||||||
showMessage(msgAttachedToStoppedInferior(), StatusBar);
|
showMessage(tr("Attached to running application"), StatusBar);
|
||||||
notifyEngineRunAndInferiorRunOk();
|
notifyEngineRunAndInferiorRunOk();
|
||||||
interruptInferior();
|
} else {
|
||||||
|
// InferiorStopOk, e.g. for "Attach to running application".
|
||||||
|
// The *stopped came in between sending the 'attach' and
|
||||||
|
// receiving its '^done'.
|
||||||
|
if (startParameters().continueAfterAttach)
|
||||||
|
continueInferiorInternal();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ResultError:
|
case ResultError:
|
||||||
|
@@ -63,7 +63,7 @@ public:
|
|||||||
StartGdbServerDialogPrivate() : dialog(0), kit(0) {}
|
StartGdbServerDialogPrivate() : dialog(0), kit(0) {}
|
||||||
|
|
||||||
DeviceProcessesDialog *dialog;
|
DeviceProcessesDialog *dialog;
|
||||||
bool startServerOnly;
|
bool attachToServer;
|
||||||
DeviceProcessItem process;
|
DeviceProcessItem process;
|
||||||
Kit *kit;
|
Kit *kit;
|
||||||
IDevice::ConstPtr device;
|
IDevice::ConstPtr device;
|
||||||
@@ -72,7 +72,7 @@ public:
|
|||||||
SshRemoteProcessRunner runner;
|
SshRemoteProcessRunner runner;
|
||||||
};
|
};
|
||||||
|
|
||||||
GdbServerStarter::GdbServerStarter(DeviceProcessesDialog *dlg, bool startServerOnly)
|
GdbServerStarter::GdbServerStarter(DeviceProcessesDialog *dlg, bool attachAfterServerStart)
|
||||||
: QObject(dlg)
|
: QObject(dlg)
|
||||||
{
|
{
|
||||||
d = new StartGdbServerDialogPrivate;
|
d = new StartGdbServerDialogPrivate;
|
||||||
@@ -80,7 +80,7 @@ GdbServerStarter::GdbServerStarter(DeviceProcessesDialog *dlg, bool startServerO
|
|||||||
d->kit = dlg->kitChooser()->currentKit();
|
d->kit = dlg->kitChooser()->currentKit();
|
||||||
d->process = dlg->currentProcess();
|
d->process = dlg->currentProcess();
|
||||||
d->device = DeviceKitInformation::device(d->kit);
|
d->device = DeviceKitInformation::device(d->kit);
|
||||||
d->startServerOnly = startServerOnly;
|
d->attachToServer = attachAfterServerStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
GdbServerStarter::~GdbServerStarter()
|
GdbServerStarter::~GdbServerStarter()
|
||||||
@@ -167,7 +167,7 @@ void GdbServerStarter::handleProcessErrorOutput()
|
|||||||
logMessage(tr("Port %1 is now accessible.").arg(port));
|
logMessage(tr("Port %1 is now accessible.").arg(port));
|
||||||
logMessage(tr("Server started on %1:%2")
|
logMessage(tr("Server started on %1:%2")
|
||||||
.arg(d->device->sshParameters().host).arg(port));
|
.arg(d->device->sshParameters().host).arg(port));
|
||||||
if (!d->startServerOnly)
|
if (d->attachToServer)
|
||||||
attach(port);
|
attach(port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -45,7 +45,8 @@ class GdbServerStarter : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GdbServerStarter(ProjectExplorer::DeviceProcessesDialog *dlg, bool startServerOnly);
|
GdbServerStarter(ProjectExplorer::DeviceProcessesDialog *dlg,
|
||||||
|
bool attachAfterServerStart);
|
||||||
~GdbServerStarter();
|
~GdbServerStarter();
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
|
@@ -263,7 +263,7 @@ AttachCoreDialog::AttachCoreDialog(QWidget *parent)
|
|||||||
d->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
|
d->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
|
||||||
d->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
d->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||||
|
|
||||||
d->kitChooser = new DebuggerKitChooser(DebuggerKitChooser::RemoteDebugging, this);
|
d->kitChooser = new DebuggerKitChooser(DebuggerKitChooser::AnyDebugging, this);
|
||||||
d->kitChooser->populate();
|
d->kitChooser->populate();
|
||||||
|
|
||||||
d->forceLocalCheckBox = new QCheckBox(this);
|
d->forceLocalCheckBox = new QCheckBox(this);
|
||||||
|
Reference in New Issue
Block a user