From 108d06c83fc269577d3d9081419f169466c6f577 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 2 Feb 2021 15:09:17 +0100 Subject: [PATCH] Debugger: Fix attaching to certain processes On platforms without /proc (Mac...) we use 'ps' to retrieve process lists, previously with '-o pid,comm,args'. This cuts off parts of the executable names that are 'too long' or contain spaces. Work around by running ps twice to retrieve arbitrarily long lines. Fixes: QTCREATORBUG-25286 Change-Id: I617b62ccb61e90a1b43b6bdd822be0f50657504e Reviewed-by: Christian Kandeler --- .../devicesupport/localprocesslist.cpp | 53 ++++++++++++------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp b/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp index fe917785793..3b8c534c983 100644 --- a/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp +++ b/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp @@ -153,13 +153,12 @@ static QList getLocalProcessesUsingProc(const QDir &procDir) } // Determine UNIX processes by running ps -static QList getLocalProcessesUsingPs() +static QMap getLocalProcessDataUsingPs(const QString &column) { - QList processes; + QMap result; QProcess psProcess; - QStringList args; - args << QLatin1String("-e") << QLatin1String("-o") << QLatin1String("pid,comm,args"); - psProcess.start(QLatin1String("ps"), args); + const QStringList args{"-e", "-o", "pid," + column}; + psProcess.start("ps", args); if (psProcess.waitForStarted()) { QByteArray output; if (Utils::SynchronousProcess::readDataFromProcess(psProcess, 30000, &output, nullptr, false)) { @@ -168,23 +167,41 @@ static QList getLocalProcessesUsingPs() const int lineCount = lines.size(); const QChar blank = QLatin1Char(' '); for (int l = 1; l < lineCount; l++) { // Skip header - const QString line = lines.at(l).simplified(); + const QString line = lines.at(l).trimmed(); const int pidSep = line.indexOf(blank); - const int cmdSep = pidSep != -1 ? line.indexOf(blank, pidSep + 1) : -1; - if (cmdSep > 0) { - const int argsSep = line.indexOf(blank, cmdSep + 1); - DeviceProcessItem procData; - procData.pid = line.left(pidSep).toInt(); - procData.cmdLine = line.mid(cmdSep + 1); - if (argsSep == -1) - procData.exe = line.mid(cmdSep + 1); - else - procData.exe = line.mid(cmdSep + 1, argsSep - cmdSep -1); - processes.push_back(procData); - } + const qint64 pid = line.left(pidSep).toLongLong(); + result[pid] = line.mid(pidSep + 1); } } } + return result; +} + +static QList getLocalProcessesUsingPs() +{ + QList processes; + + // cmdLines are full command lines, usually with absolute path, + // exeNames only the file part of the executable's path. + const QMap exeNames = getLocalProcessDataUsingPs("comm"); + const QMap cmdLines = getLocalProcessDataUsingPs("args"); + + for (auto it = exeNames.begin(), end = exeNames.end(); it != end; ++it) { + const qint64 pid = it.key(); + if (pid <= 0) + continue; + const QString cmdLine = cmdLines.value(pid); + if (cmdLines.isEmpty()) + continue; + const QString exeName = it.value(); + if (exeName.isEmpty()) + continue; + const int pos = cmdLine.indexOf(exeName); + if (pos == -1) + continue; + processes.append({pid, cmdLine, cmdLine.left(pos + exeName.size())}); + } + return processes; }