diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp index fd4137f78c4..b23253c9ef8 100644 --- a/src/plugins/debugger/debuggerdialogs.cpp +++ b/src/plugins/debugger/debuggerdialogs.cpp @@ -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); diff --git a/src/plugins/debugger/debuggerdialogs.h b/src/plugins/debugger/debuggerdialogs.h index 32296a1f478..eee9ee11c4a 100644 --- a/src/plugins/debugger/debuggerdialogs.h +++ b/src/plugins/debugger/debuggerdialogs.h @@ -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; diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 193691d675e..2af73f2abc3 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -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(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...")); diff --git a/src/plugins/debugger/debuggerplugin.h b/src/plugins/debugger/debuggerplugin.h index 247f6b19e11..ba8241cb03b 100644 --- a/src/plugins/debugger/debuggerplugin.h +++ b/src/plugins/debugger/debuggerplugin.h @@ -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 diff --git a/src/plugins/debugger/gdb/attachgdbadapter.cpp b/src/plugins/debugger/gdb/attachgdbadapter.cpp index 2028538a194..bee49e47ede 100644 --- a/src/plugins/debugger/gdb/attachgdbadapter.cpp +++ b/src/plugins/debugger/gdb/attachgdbadapter.cpp @@ -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: diff --git a/src/plugins/debugger/gdb/startgdbserverdialog.cpp b/src/plugins/debugger/gdb/startgdbserverdialog.cpp index 346668ea19e..68a87c9f486 100644 --- a/src/plugins/debugger/gdb/startgdbserverdialog.cpp +++ b/src/plugins/debugger/gdb/startgdbserverdialog.cpp @@ -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); } } diff --git a/src/plugins/debugger/gdb/startgdbserverdialog.h b/src/plugins/debugger/gdb/startgdbserverdialog.h index 99d61aa7434..724d71a9479 100644 --- a/src/plugins/debugger/gdb/startgdbserverdialog.h +++ b/src/plugins/debugger/gdb/startgdbserverdialog.h @@ -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(); diff --git a/src/plugins/debugger/loadcoredialog.cpp b/src/plugins/debugger/loadcoredialog.cpp index e2b8063a43c..e549d4e04aa 100644 --- a/src/plugins/debugger/loadcoredialog.cpp +++ b/src/plugins/debugger/loadcoredialog.cpp @@ -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);