blob: cf0a3c510d7955e9ebde169845af65821b5a44b5 [file] [log] [blame]
#include "process_manager.h"
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <functional>
#include <iostream>
#include <memory>
#include "utils/bash_command.h"
#include "utils/fs/disk_file_system.h"
#include "utils/log.h"
#include "utils/trace.h"
using std::shared_ptr;
using std::string;
using std::vector;
// Command to attach an jvmti agent. It should be followed with two parameters:
// 1. the app/package name, 2. the location of the agent so.
const char* const kAttachAgentCmd = "cmd activity attach-agent";
namespace profiler {
int ProcessManager::GetPidForBinary(const std::string& binary_name) const {
// Retrieve the list of all processes on the system.
vector<Process> processes = this->GetAllProcesses();
// Search process
for (Process process : processes) {
if (process.binary_name == binary_name) {
return process.pid;
}
}
return -1;
}
vector<Process> ProcessManager::GetAllProcesses() const {
Trace trace("ProcesManager::GetAllProcesses");
vector<Process> processes;
// List /proc/ and retrieve:
// - /proc/pid for process id.
// - /proc/pid/cmd for command-line.
// Only if both values were retrieved the process is added to the return
// vector.
DiskFileSystem fs;
fs.WalkDir(
"/proc",
[&](const PathStat& path_stat) {
if (path_stat.type() != PathStat::Type::DIR) return;
int pid = atoi(path_stat.rel_path().c_str());
if (pid == 0) return;
std::stringstream cmd_path;
cmd_path << "/proc/" << pid << "/cmdline";
shared_ptr<File> cmdline_file = fs.GetFile(cmd_path.str());
if (!cmdline_file->Exists()) return; // The process already died.
string cmdline = cmdline_file->Contents();
// cmdline contains a sequence of null terminated string. We want
// to keep only the first one to extract the binary name.
string binary_name = string(cmdline, 0, strlen(cmdline.c_str()));
processes.push_back(Process(pid, cmdline, binary_name));
},
1);
return processes;
}
bool ProcessManager::IsPidAlive(int pid) const {
DiskFileSystem fs;
std::stringstream process_path;
process_path << "/proc/";
process_path << pid;
return fs.GetDir(process_path.str())->Exists();
}
std::string ProcessManager::GetCmdlineForPid(int pid) {
std::ostringstream os;
os << "/proc/" << pid << "/cmdline";
BashCommandRunner cat("cat");
string output;
if (cat.Run(os.str(), &output)) {
return output;
}
return "";
}
std::string ProcessManager::GetAttachAgentCommand() { return kAttachAgentCmd; }
std::string ProcessManager::GetAttachAgentParams(
const std::string& app_name, const std::string& data_path,
const std::string& config_path, const std::string& lib_file_name) {
std::ostringstream attach_params;
attach_params << app_name << " " << data_path << "/code_cache/"
<< lib_file_name << "=" << config_path;
return attach_params.str();
}
std::string ProcessManager::GetPackageNameFromAppName(
const std::string& app_name) {
return app_name.substr(0, app_name.find(":"));
}
Process::Process(pid_t pid, const string& cmdline,
const std::string& binary_name)
: pid(pid), cmdline(cmdline), binary_name(binary_name) {}
} // namespace profiler