Changeset View
Changeset View
Standalone View
Standalone View
src/backtracegenerator.cpp
Show First 20 Lines • Show All 50 Lines • ▼ Show 20 Line(s) | |||||
51 | BacktraceGenerator::~BacktraceGenerator() | 51 | BacktraceGenerator::~BacktraceGenerator() | ||
52 | { | 52 | { | ||
53 | if (m_proc && m_proc->state() == QProcess::Running) { | 53 | if (m_proc && m_proc->state() == QProcess::Running) { | ||
54 | qCWarning(DRKONQI_LOG) << "Killing running debugger instance"; | 54 | qCWarning(DRKONQI_LOG) << "Killing running debugger instance"; | ||
55 | m_proc->disconnect(this); | 55 | m_proc->disconnect(this); | ||
56 | m_proc->terminate(); | 56 | m_proc->terminate(); | ||
57 | if (!m_proc->waitForFinished(10000)) { | 57 | if (!m_proc->waitForFinished(10000)) { | ||
58 | m_proc->kill(); | 58 | m_proc->kill(); | ||
59 | m_proc->waitForFinished(); | 59 | // lldb can become "stuck" on OS X; just mark m_proc as to be deleted later rather | ||
60 | } | 60 | // than waiting a potentially very long time for it to heed the kill() request. | ||
61 | m_proc->deleteLater(); | ||||
62 | } else { | ||||
61 | delete m_proc; | 63 | delete m_proc; | ||
64 | } | ||||
62 | delete m_temp; | 65 | delete m_temp; | ||
63 | } | 66 | } | ||
64 | } | 67 | } | ||
65 | 68 | | |||
66 | bool BacktraceGenerator::start() | 69 | bool BacktraceGenerator::start() | ||
67 | { | 70 | { | ||
68 | //they should always be null before entering this function. | 71 | //they should always be null before entering this function. | ||
69 | Q_ASSERT(!m_proc); | 72 | Q_ASSERT(!m_proc); | ||
Show All 21 Lines | |||||
91 | 94 | | |||
92 | // start the debugger | 95 | // start the debugger | ||
93 | QString str = m_debugger.command(); | 96 | QString str = m_debugger.command(); | ||
94 | Debugger::expandString(str, Debugger::ExpansionUsageShell, m_temp->fileName()); | 97 | Debugger::expandString(str, Debugger::ExpansionUsageShell, m_temp->fileName()); | ||
95 | 98 | | |||
96 | *m_proc << KShell::splitArgs(str); | 99 | *m_proc << KShell::splitArgs(str); | ||
97 | m_proc->setOutputChannelMode(KProcess::OnlyStdoutChannel); | 100 | m_proc->setOutputChannelMode(KProcess::OnlyStdoutChannel); | ||
98 | m_proc->setNextOpenMode(QIODevice::ReadWrite | QIODevice::Text); | 101 | m_proc->setNextOpenMode(QIODevice::ReadWrite | QIODevice::Text); | ||
102 | // check if the debugger should take its input from a file we'll generate, | ||||
103 | // and take the appropriate steps if so | ||||
104 | QString stdinFile = m_debugger.backendValueOfParameter(QStringLiteral("ExecInputFile")); | ||||
105 | Debugger::expandString(stdinFile, Debugger::ExpansionUsageShell, m_temp->fileName()); | ||||
106 | if (!stdinFile.isEmpty() && QFile::exists(stdinFile)) { | ||||
107 | m_proc->setStandardInputFile(stdinFile); | ||||
108 | } | ||||
99 | connect(m_proc, &KProcess::readyReadStandardOutput, this, &BacktraceGenerator::slotReadInput); | 109 | connect(m_proc, &KProcess::readyReadStandardOutput, this, &BacktraceGenerator::slotReadInput); | ||
100 | connect(m_proc, static_cast<void (KProcess::*)(int, QProcess::ExitStatus)>(&KProcess::finished), this, &BacktraceGenerator::slotProcessExited); | 110 | connect(m_proc, static_cast<void (KProcess::*)(int, QProcess::ExitStatus)>(&KProcess::finished), this, &BacktraceGenerator::slotProcessExited); | ||
101 | 111 | | |||
102 | m_proc->start(); | 112 | m_proc->start(); | ||
103 | if (!m_proc->waitForStarted()) { | 113 | if (!m_proc->waitForStarted()) { | ||
104 | //we mustn't keep these around... | 114 | //we mustn't keep these around... | ||
105 | m_proc->deleteLater(); | 115 | m_proc->deleteLater(); | ||
106 | m_temp->deleteLater(); | 116 | m_temp->deleteLater(); | ||
107 | m_proc = nullptr; | 117 | m_proc = nullptr; | ||
108 | m_temp = nullptr; | 118 | m_temp = nullptr; | ||
109 | 119 | | |||
110 | m_state = FailedToStart; | 120 | m_state = FailedToStart; | ||
111 | emit failedToStart(); | 121 | emit failedToStart(); | ||
112 | return false; | 122 | return false; | ||
113 | } | 123 | } | ||
114 | 124 | | |||
115 | return true; | 125 | return true; | ||
116 | } | 126 | } | ||
117 | 127 | | |||
118 | void BacktraceGenerator::slotReadInput() | 128 | void BacktraceGenerator::slotReadInput() | ||
119 | { | 129 | { | ||
130 | if (!m_proc) { | ||||
131 | // this can happen with lldb after we detected that it detached from the debuggee. | ||||
132 | return; | ||||
133 | } | ||||
134 | | ||||
120 | // we do not know if the output array ends in the middle of an utf-8 sequence | 135 | // we do not know if the output array ends in the middle of an utf-8 sequence | ||
121 | m_output += m_proc->readAllStandardOutput(); | 136 | m_output += m_proc->readAllStandardOutput(); | ||
122 | 137 | | |||
123 | int pos; | 138 | int pos; | ||
124 | while ((pos = m_output.indexOf('\n')) != -1) { | 139 | while ((pos = m_output.indexOf('\n')) != -1) { | ||
davidedmundson: this seems dangerous for the other clients.
It's not unfeasible for a process to have a load… | |||||
You mean move the check on QProcess::Running into the if (line.startsWith(QLatin1String("Process ")) && line.endsWith(QLatin1String(" detached"))) ? rjvbb: You mean move the check on QProcess::Running into the `if (line.startsWith(QLatin1String… | |||||
davidedmundson: Yes
Also is it worth adding a "break;" there? | |||||
A break instead of or in addition to the return? I think I'd prefer the return, unless you think that maybe someday there will be some extra steps to be taken after the while loop? rjvbb: A break instead of or in addition to the return? I think I'd prefer the return, unless you… | |||||
125 | QString line = QString::fromLocal8Bit(m_output.constData(), pos + 1); | 140 | QString line = QString::fromLocal8Bit(m_output.constData(), pos + 1); | ||
126 | m_output.remove(0, pos + 1); | 141 | m_output.remove(0, pos + 1); | ||
127 | 142 | | |||
128 | emit newLine(line); | 143 | emit newLine(line); | ||
144 | line = line.simplified(); | ||||
145 | if (line.startsWith(QLatin1String("Process ")) && line.endsWith(QLatin1String(" detached"))) { | ||||
146 | // lldb is acting on a detach command (in lldbrc) | ||||
147 | // Anything following this line doesn't interest us, and lldb has been known | ||||
148 | // to turn into a zombie instead of exitting, thereby blocking us. | ||||
149 | // Tell the process to quit if it's still running, and pretend it did. | ||||
150 | if (m_proc && m_proc->state() == QProcess::Running) { | ||||
151 | m_proc->terminate(); | ||||
152 | if (!m_proc->waitForFinished(500)) { | ||||
153 | m_proc->kill(); | ||||
154 | } | ||||
155 | if (m_proc) { | ||||
156 | slotProcessExited(0, QProcess::NormalExit); | ||||
157 | } | ||||
158 | } | ||||
159 | return; | ||||
160 | } | ||||
129 | } | 161 | } | ||
130 | } | 162 | } | ||
131 | 163 | | |||
132 | void BacktraceGenerator::slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus) | 164 | void BacktraceGenerator::slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus) | ||
133 | { | 165 | { | ||
134 | //these are useless now | 166 | //these are useless now | ||
135 | m_proc->deleteLater(); | 167 | m_proc->deleteLater(); | ||
136 | m_temp->deleteLater(); | 168 | m_temp->deleteLater(); | ||
Show All 29 Lines |
this seems dangerous for the other clients.
It's not unfeasible for a process to have a load of data still in the buffer when it quits.
I don't know lldb, but it seems you can probably move this to ~149