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);
|
||||
setWindowTitle(tr("Start Debugger"));
|
||||
|
||||
d->kitChooser = new DebuggerKitChooser(DebuggerKitChooser::RemoteDebugging, this);
|
||||
d->kitChooser = new DebuggerKitChooser(DebuggerKitChooser::AnyDebugging, this);
|
||||
d->kitChooser->populate();
|
||||
|
||||
d->portSpinBox = new QSpinBox(this);
|
||||
|
@@ -59,12 +59,14 @@ class StartApplicationParameters;
|
||||
class StartApplicationDialogPrivate;
|
||||
class StartRemoteEngineDialogPrivate;
|
||||
|
||||
class DebuggerKitChooser : public ProjectExplorer::KitChooser {
|
||||
class DebuggerKitChooser : public ProjectExplorer::KitChooser
|
||||
{
|
||||
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:
|
||||
bool kitMatches(const ProjectExplorer::Kit *k) const;
|
||||
|
@@ -612,7 +612,8 @@ public:
|
||||
m_threadBox->setCurrentIndex(index);
|
||||
m_threadBox->blockSignals(state);
|
||||
}
|
||||
DebuggerRunControl *attachToRunningProcess(Kit *kit, DeviceProcessItem process);
|
||||
|
||||
DebuggerRunControl *attachToRunningProcess(Kit *kit, DeviceProcessItem process, bool contAfterAttach);
|
||||
|
||||
void writeSettings()
|
||||
{
|
||||
@@ -710,13 +711,10 @@ public:
|
||||
|
||||
void startAndDebugApplication();
|
||||
void startRemoteCdbSession();
|
||||
void startRemoteServer();
|
||||
void startRemoteServerAndAttachToProcess();
|
||||
void attachToRemoteServer();
|
||||
void attachToProcess(bool startServerOnly);
|
||||
void attachToRunningApplication();
|
||||
void attachToUnstartedApplicationDialog();
|
||||
void attachToFoundProcess();
|
||||
void continueOnAttach(Debugger::DebuggerState state);
|
||||
void attachToQmlPort();
|
||||
Q_SLOT void runScheduled();
|
||||
void attachCore();
|
||||
@@ -1400,22 +1398,10 @@ void DebuggerPluginPrivate::attachToRemoteServer()
|
||||
}
|
||||
}
|
||||
|
||||
void DebuggerPluginPrivate::startRemoteServer()
|
||||
void DebuggerPluginPrivate::startRemoteServerAndAttachToProcess()
|
||||
{
|
||||
attachToProcess(true);
|
||||
}
|
||||
|
||||
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());
|
||||
auto kitChooser = new DebuggerKitChooser(DebuggerKitChooser::AnyDebugging);
|
||||
auto dlg = new DeviceProcessesDialog(kitChooser, ICore::dialogParent());
|
||||
dlg->addAcceptButton(DeviceProcessesDialog::tr("&Attach to Process"));
|
||||
dlg->showAllDevices();
|
||||
if (dlg->exec() == QDialog::Rejected) {
|
||||
@@ -1429,62 +1415,63 @@ void DebuggerPluginPrivate::attachToProcess(bool startServerOnly)
|
||||
IDevice::ConstPtr device = DeviceKitInformation::device(kit);
|
||||
QTC_ASSERT(device, return);
|
||||
|
||||
if (device->type() != PE::DESKTOP_DEVICE_TYPE) {
|
||||
GdbServerStarter *starter = new GdbServerStarter(dlg, startServerOnly);
|
||||
starter->run();
|
||||
GdbServerStarter *starter = new GdbServerStarter(dlg, true);
|
||||
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 {
|
||||
attachToRunningProcess(kit, dlg->currentProcess());
|
||||
GdbServerStarter *starter = new GdbServerStarter(dlg, true);
|
||||
starter->run();
|
||||
}
|
||||
}
|
||||
|
||||
void DebuggerPluginPrivate::attachToUnstartedApplicationDialog()
|
||||
{
|
||||
UnstartedAppWatcherDialog *dlg = new UnstartedAppWatcherDialog(ICore::dialogParent());
|
||||
auto dlg = new UnstartedAppWatcherDialog(ICore::dialogParent());
|
||||
|
||||
connect(dlg, &QDialog::finished, dlg, &QObject::deleteLater);
|
||||
connect(dlg, &UnstartedAppWatcherDialog::processFound, this, &DebuggerPluginPrivate::attachToFoundProcess);
|
||||
connect(dlg, &UnstartedAppWatcherDialog::processFound, this, [this, dlg] {
|
||||
DebuggerRunControl *rc = attachToRunningProcess(dlg->currentKit(),
|
||||
dlg->currentProcess(),
|
||||
dlg->continueOnAttach());
|
||||
if (!rc)
|
||||
return;
|
||||
|
||||
if (dlg->hideOnAttach())
|
||||
connect(rc, &RunControl::finished, dlg, &UnstartedAppWatcherDialog::startWatching);
|
||||
});
|
||||
|
||||
dlg->show();
|
||||
}
|
||||
|
||||
void DebuggerPluginPrivate::attachToFoundProcess()
|
||||
{
|
||||
UnstartedAppWatcherDialog *dlg = qobject_cast<UnstartedAppWatcherDialog *>(QObject::sender());
|
||||
if (!dlg)
|
||||
return;
|
||||
|
||||
DebuggerRunControl *rc = attachToRunningProcess(dlg->currentKit(), dlg->currentProcess());
|
||||
if (!rc)
|
||||
return;
|
||||
|
||||
if (dlg->hideOnAttach())
|
||||
connect(rc, &RunControl::finished, dlg, &UnstartedAppWatcherDialog::startWatching);
|
||||
|
||||
if (dlg->continueOnAttach()) {
|
||||
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,
|
||||
DeviceProcessItem process)
|
||||
DeviceProcessItem process, bool contAfterAttach)
|
||||
{
|
||||
QTC_ASSERT(kit, return 0);
|
||||
IDevice::ConstPtr device = DeviceKitInformation::device(kit);
|
||||
QTC_ASSERT(device, return 0);
|
||||
if (process.pid == 0) {
|
||||
AsynchronousMessageBox::warning(tr("Warning"),
|
||||
tr("Cannot attach to process with PID 0"));
|
||||
AsynchronousMessageBox::warning(tr("Warning"), tr("Cannot attach to process with PID 0"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1512,6 +1499,7 @@ DebuggerRunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit,
|
||||
sp.executable = process.exe;
|
||||
sp.startMode = AttachExternal;
|
||||
sp.closeMode = DetachAtClose;
|
||||
sp.continueAfterAttach = contAfterAttach;
|
||||
return DebuggerRunControlFactory::createAndScheduleRun(sp);
|
||||
}
|
||||
|
||||
@@ -2648,7 +2636,7 @@ void DebuggerPluginPrivate::extensionsInitialized()
|
||||
|
||||
act = m_startRemoteServerAction = new QAction(this);
|
||||
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->setText(tr("Attach to Running Application..."));
|
||||
|
@@ -54,6 +54,8 @@ private:
|
||||
QObject *remoteCommand(const QStringList &options, const QStringList &arguments);
|
||||
ShutdownFlag aboutToShutdown();
|
||||
void extensionsInitialized();
|
||||
|
||||
// Called from AppOutputPane::attachToRunControl().
|
||||
Q_SLOT void attachExternalApplication(ProjectExplorer::RunControl *rc);
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
|
@@ -89,12 +89,17 @@ void GdbAttachEngine::handleAttach(const DebuggerResponse &response)
|
||||
case ResultRunning:
|
||||
showMessage(_("INFERIOR ATTACHED"));
|
||||
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'
|
||||
// So acknowledge the current state and put a delayed 'continue' in the pipe.
|
||||
showMessage(msgAttachedToStoppedInferior(), StatusBar);
|
||||
showMessage(tr("Attached to running application"), StatusBar);
|
||||
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;
|
||||
case ResultError:
|
||||
|
@@ -63,7 +63,7 @@ public:
|
||||
StartGdbServerDialogPrivate() : dialog(0), kit(0) {}
|
||||
|
||||
DeviceProcessesDialog *dialog;
|
||||
bool startServerOnly;
|
||||
bool attachToServer;
|
||||
DeviceProcessItem process;
|
||||
Kit *kit;
|
||||
IDevice::ConstPtr device;
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
SshRemoteProcessRunner runner;
|
||||
};
|
||||
|
||||
GdbServerStarter::GdbServerStarter(DeviceProcessesDialog *dlg, bool startServerOnly)
|
||||
GdbServerStarter::GdbServerStarter(DeviceProcessesDialog *dlg, bool attachAfterServerStart)
|
||||
: QObject(dlg)
|
||||
{
|
||||
d = new StartGdbServerDialogPrivate;
|
||||
@@ -80,7 +80,7 @@ GdbServerStarter::GdbServerStarter(DeviceProcessesDialog *dlg, bool startServerO
|
||||
d->kit = dlg->kitChooser()->currentKit();
|
||||
d->process = dlg->currentProcess();
|
||||
d->device = DeviceKitInformation::device(d->kit);
|
||||
d->startServerOnly = startServerOnly;
|
||||
d->attachToServer = attachAfterServerStart;
|
||||
}
|
||||
|
||||
GdbServerStarter::~GdbServerStarter()
|
||||
@@ -167,7 +167,7 @@ void GdbServerStarter::handleProcessErrorOutput()
|
||||
logMessage(tr("Port %1 is now accessible.").arg(port));
|
||||
logMessage(tr("Server started on %1:%2")
|
||||
.arg(d->device->sshParameters().host).arg(port));
|
||||
if (!d->startServerOnly)
|
||||
if (d->attachToServer)
|
||||
attach(port);
|
||||
}
|
||||
}
|
||||
|
@@ -45,7 +45,8 @@ class GdbServerStarter : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GdbServerStarter(ProjectExplorer::DeviceProcessesDialog *dlg, bool startServerOnly);
|
||||
GdbServerStarter(ProjectExplorer::DeviceProcessesDialog *dlg,
|
||||
bool attachAfterServerStart);
|
||||
~GdbServerStarter();
|
||||
|
||||
void run();
|
||||
|
@@ -263,7 +263,7 @@ AttachCoreDialog::AttachCoreDialog(QWidget *parent)
|
||||
d->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
|
||||
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->forceLocalCheckBox = new QCheckBox(this);
|
||||
|
Reference in New Issue
Block a user