fix: 修复AM启动崩溃的问题

部分root进程在/proc文件系统查找不到exe、cwd、cmdline信息,将其过滤掉

Log:
Task: https://pms.uniontech.com/task-view-155485.html
Influence: AM正常启动
Change-Id: Ibc6fd227d0ec1505de3c1a96be1726a422a05135
This commit is contained in:
weizhixiang 2022-06-27 10:15:19 +08:00
parent dfa232bb98
commit d6a7ca131a
4 changed files with 77 additions and 47 deletions

View File

@ -24,26 +24,36 @@
#include <QFileInfo> #include <QFileInfo>
#include <QDir> #include <QDir>
#include <QDebug>
ProcessInfo::ProcessInfo(int pid) ProcessInfo::ProcessInfo(int pid)
: hasPid(true) : m_hasPid(true)
, process(Process(pid)) , m_process(Process(pid))
, m_isValid(true)
{ {
if (pid == 0) if (pid == 0)
return; return;
// exe // exe
exe = process.getExe(); m_exe = m_process.getExe();
// cwd // cwd
cwd = process.getCwd(); m_cwd = m_process.getCwd();
// cmdline // cmdline
cmdLine = process.getCmdLine(); m_cmdLine = m_process.getCmdLine();
// ppid // 部分root进程在/proc文件系统查找不到exe、cwd、cmdline信息
Status pstatus = process.getStatus(); if (m_exe.empty() || m_cwd.empty() || m_cmdLine.size() == 0) {
if (pstatus.size() > 0) { m_isValid = false;
int ppid = process.getPpid(); return;
} }
// ppid
Status pstatus = m_process.getStatus();
if (pstatus.size() > 0) {
int ppid = m_process.getPpid();
}
// args // args
qInfo() << "ProcessInfo: exe=" << m_exe.c_str() << " cwd=" << m_cwd.c_str() << " cmdLine=" << (m_cmdLine[0].empty() ? " " : m_cmdLine[0].c_str());
auto verifyExe = [](std::string exe, std::string cwd, std::string firstArg){ auto verifyExe = [](std::string exe, std::string cwd, std::string firstArg){
if (firstArg.size() == 0) if (firstArg.size() == 0)
return false; return false;
@ -57,91 +67,102 @@ ProcessInfo::ProcessInfo(int pid)
return exe == firstArg; return exe == firstArg;
}; };
if (!verifyExe(exe, cwd, cmdLine[0])) {
auto parts = DString::splitStr(cmdLine[0], ' '); if (!m_cmdLine[0].empty()) {
// try again if (!verifyExe(m_exe, m_cwd, m_cmdLine[0])) {
if (verifyExe(exe, cwd, parts[0])) { auto parts = DString::splitStr(m_cmdLine[0], ' ');
for (int j = 1; j < parts.size(); j++) { // try again
args.push_back(parts[j]); if (verifyExe(m_exe, m_cwd, parts[0])) {
for (int j = 1; j < parts.size(); j++) {
m_args.push_back(parts[j]);
}
for (int i = 1; i < m_cmdLine.size(); i++) {
m_args.push_back(m_cmdLine[i]);
}
} }
for (int i = 1; i < cmdLine.size(); i++) { } else {
args.push_back(cmdLine[i]); for (int i = 1; i < m_cmdLine.size(); i++) {
m_args.push_back(m_cmdLine[i]);
} }
} }
} else {
for (int i = 1; i < cmdLine.size(); i++) {
args.push_back(cmdLine[i]);
}
} }
} }
ProcessInfo::ProcessInfo(std::vector<std::string> &cmd) ProcessInfo::ProcessInfo(std::vector<std::string> &cmd)
: hasPid(false) : m_hasPid(false)
, process(Process()) , m_isValid(true)
, m_process(Process())
{ {
if (cmd.size() == 0) if (cmd.size() == 0) {
m_isValid = false;
return; return;
}
cmdLine = cmd; m_cmdLine = cmd;
exe = cmd[0]; m_exe = cmd[0];
for (ulong i=0; i < cmd.size(); i++) { for (ulong i=0; i < cmd.size(); i++) {
if (i > 0) { if (i > 0) {
args.push_back(cmd[i]); m_args.push_back(cmd[i]);
} }
} }
} }
std::string ProcessInfo::getEnv(std::string key) std::string ProcessInfo::getEnv(std::string key)
{ {
return process.getEnv(key); return m_process.getEnv(key);
} }
std::vector<std::string> ProcessInfo::getCmdLine() std::vector<std::string> ProcessInfo::getCmdLine()
{ {
return cmdLine; return m_cmdLine;
} }
std::vector<std::string> ProcessInfo::getArgs() std::vector<std::string> ProcessInfo::getArgs()
{ {
return args; return m_args;
} }
int ProcessInfo::getPid() int ProcessInfo::getPid()
{ {
return process.getPid(); return m_process.getPid();
} }
int ProcessInfo::getPpid() int ProcessInfo::getPpid()
{ {
return process.getPpid(); return m_process.getPpid();
} }
bool ProcessInfo::initWithPid() bool ProcessInfo::initWithPid()
{ {
return hasPid; return m_hasPid;
}
bool ProcessInfo::isValid()
{
return m_isValid;
} }
std::string ProcessInfo::getExe() std::string ProcessInfo::getExe()
{ {
return exe; return m_exe;
} }
std::string ProcessInfo::getOneCommandLine() std::string ProcessInfo::getOneCommandLine()
{ {
std::string cmdline = getJoinedExeArgs(); std::string cmdline = getJoinedExeArgs();
return "sh -c 'cd " + cwd + "; exec " + cmdline + ";'"; return "sh -c 'cd " + m_cwd + "; exec " + cmdline + ";'";
} }
std::string ProcessInfo::getShellScriptLines() std::string ProcessInfo::getShellScriptLines()
{ {
std::string cmdline = getJoinedExeArgs(); std::string cmdline = getJoinedExeArgs();
return "#!/bin/sh\n cd " + cwd + "\n exec " + cmdline + "\n"; return "#!/bin/sh\n cd " + m_cwd + "\n exec " + cmdline + "\n";
} }
std::string ProcessInfo::getJoinedExeArgs() std::string ProcessInfo::getJoinedExeArgs()
{ {
std::string ret = "\"" + exe + "\""; std::string ret = "\"" + m_exe + "\"";
for (auto arg : args) { for (auto arg : m_args) {
ret += " \"" + arg + "\""; ret += " \"" + arg + "\"";
} }

View File

@ -40,6 +40,7 @@ public:
int getPid(); int getPid();
int getPpid(); int getPpid();
bool initWithPid(); bool initWithPid();
bool isValid();
std::string getExe(); std::string getExe();
std::string getOneCommandLine(); std::string getOneCommandLine();
std::string getShellScriptLines(); std::string getShellScriptLines();
@ -47,13 +48,14 @@ public:
private: private:
std::string getJoinedExeArgs(); std::string getJoinedExeArgs();
std::vector<std::string> cmdLine; std::vector<std::string> m_cmdLine;
std::vector<std::string> args; std::vector<std::string> m_args;
std::string exe; std::string m_exe;
std::string cwd; std::string m_cwd;
bool hasPid; bool m_hasPid;
Process process; bool m_isValid;
Process m_process;
}; };
#endif // PROCESSINFO_H #endif // PROCESSINFO_H

View File

@ -34,7 +34,11 @@ class WindowInfoBase
{ {
public: public:
WindowInfoBase() : entry(nullptr), app(nullptr), processInfo(nullptr) {} WindowInfoBase() : entry(nullptr), app(nullptr), processInfo(nullptr) {}
virtual ~WindowInfoBase() {} virtual ~WindowInfoBase() {
if (processInfo) {
delete processInfo;
}
}
virtual bool shouldSkip() = 0; virtual bool shouldSkip() = 0;

View File

@ -416,12 +416,15 @@ void WindowInfoX::updateProcessInfo()
if (processInfo) if (processInfo)
delete processInfo; delete processInfo;
qInfo() << "updateProcessInfo: pid=" << pid;
processInfo = new ProcessInfo(pid); processInfo = new ProcessInfo(pid);
if (!processInfo) { if (!processInfo->isValid()) {
// try WM_COMMAND // try WM_COMMAND
auto wmComand = XCB->getWMCommand(winId); auto wmComand = XCB->getWMCommand(winId);
if (wmComand.size() > 0) if (wmComand.size() > 0) {
delete processInfo;
processInfo = new ProcessInfo(wmComand); processInfo = new ProcessInfo(wmComand);
}
} }
qInfo() << "updateProcessInfo: pid is " << pid; qInfo() << "updateProcessInfo: pid is " << pid;