linux: Read /proc/<pid> files via PtraceConnection

Bug: crashpad:250
Change-Id: I93c8944c48a17bd2c2b34cd9b8d81750cf80229c
Reviewed-on: https://chromium-review.googlesource.com/1200311
Commit-Queue: Joshua Peraza <jperaza@chromium.org>
Reviewed-by: Mark Mentovai <mark@chromium.org>
This commit is contained in:
Joshua Peraza 2018-09-10 09:09:21 -07:00 committed by Commit Bot
parent a521447214
commit 78bf924fa6
6 changed files with 33 additions and 22 deletions

View File

@ -236,7 +236,7 @@ bool ProcessReaderLinux::CPUTimes(timeval* user_time,
for (const Thread& thread : threads_) { for (const Thread& thread : threads_) {
ProcStatReader stat; ProcStatReader stat;
if (!stat.Initialize(thread.tid)) { if (!stat.Initialize(connection_, thread.tid)) {
return false; return false;
} }

View File

@ -43,9 +43,12 @@ ProcStatReader::ProcStatReader()
ProcStatReader::~ProcStatReader() {} ProcStatReader::~ProcStatReader() {}
bool ProcStatReader::Initialize(pid_t tid) { bool ProcStatReader::Initialize(PtraceConnection* connection, pid_t tid) {
INITIALIZATION_STATE_SET_INITIALIZING(initialized_); INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
if (!ReadFile(tid)) {
char path[32];
snprintf(path, arraysize(path), "/proc/%d/stat", tid);
if (!connection->ReadFileContents(base::FilePath(path), &contents_)) {
return false; return false;
} }
@ -110,15 +113,6 @@ bool ProcStatReader::StartTime(timeval* start_time) const {
return true; return true;
} }
bool ProcStatReader::ReadFile(pid_t tid) {
char path[32];
snprintf(path, arraysize(path), "/proc/%d/stat", tid);
if (!LoggingReadEntireFile(base::FilePath(path), &contents_)) {
return false;
}
return true;
}
bool ProcStatReader::FindColumn(int col_index, const char** column) const { bool ProcStatReader::FindColumn(int col_index, const char** column) const {
size_t position = third_column_position_; size_t position = third_column_position_;
for (int index = 2; index < col_index; ++index) { for (int index = 2; index < col_index; ++index) {

View File

@ -22,6 +22,7 @@
#include <string> #include <string>
#include "base/macros.h" #include "base/macros.h"
#include "util/linux/ptrace_connection.h"
#include "util/misc/initialization_state_dcheck.h" #include "util/misc/initialization_state_dcheck.h"
namespace crashpad { namespace crashpad {
@ -36,8 +37,10 @@ class ProcStatReader {
//! //!
//! This method must be successfully called before calling any other. //! This method must be successfully called before calling any other.
//! //!
//! \param[in] connection A connection to the process to which the target
//! thread belongs.
//! \param[in] tid The thread ID to read the stat file for. //! \param[in] tid The thread ID to read the stat file for.
bool Initialize(pid_t tid); bool Initialize(PtraceConnection* connection, pid_t tid);
//! \brief Determines the time the thread has spent executing in user mode. //! \brief Determines the time the thread has spent executing in user mode.
//! //!
@ -64,7 +67,6 @@ class ProcStatReader {
bool StartTime(timeval* start_time) const; bool StartTime(timeval* start_time) const;
private: private:
bool ReadFile(pid_t tid);
bool FindColumn(int index, const char** column) const; bool FindColumn(int index, const char** column) const;
bool ReadTimeAtIndex(int index, timeval* time_val) const; bool ReadTimeAtIndex(int index, timeval* time_val) const;

View File

@ -20,6 +20,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "test/linux/fake_ptrace_connection.h"
#include "util/thread/thread.h" #include "util/thread/thread.h"
namespace crashpad { namespace crashpad {
@ -27,8 +28,11 @@ namespace test {
namespace { namespace {
TEST(ProcStatReader, Basic) { TEST(ProcStatReader, Basic) {
FakePtraceConnection connection;
ASSERT_TRUE(connection.Initialize(getpid()));
ProcStatReader stat; ProcStatReader stat;
ASSERT_TRUE(stat.Initialize(getpid())); ASSERT_TRUE(stat.Initialize(&connection, getpid()));
timeval start_time; timeval start_time;
ASSERT_TRUE(stat.StartTime(&start_time)); ASSERT_TRUE(stat.StartTime(&start_time));
@ -53,8 +57,11 @@ pid_t gettid() {
} }
void GetStartTime(timeval* start_time) { void GetStartTime(timeval* start_time) {
FakePtraceConnection connection;
ASSERT_TRUE(connection.Initialize(getpid()));
ProcStatReader stat; ProcStatReader stat;
ASSERT_TRUE(stat.Initialize(gettid())); ASSERT_TRUE(stat.Initialize(&connection, gettid()));
ASSERT_TRUE(stat.StartTime(start_time)); ASSERT_TRUE(stat.StartTime(start_time));
} }

View File

@ -174,6 +174,7 @@ class ProcessInfo {
// multiple successive calls will always produce the same return value and out // multiple successive calls will always produce the same return value and out
// parameters. This is necessary for intergration with the Snapshot interface. // parameters. This is necessary for intergration with the Snapshot interface.
// See https://crashpad.chromium.org/bug/9. // See https://crashpad.chromium.org/bug/9.
PtraceConnection* connection_;
std::set<gid_t> supplementary_groups_; std::set<gid_t> supplementary_groups_;
mutable timeval start_time_; mutable timeval start_time_;
pid_t pid_; pid_t pid_;

View File

@ -20,13 +20,15 @@
#include "base/logging.h" #include "base/logging.h"
#include "util/file/delimited_file_reader.h" #include "util/file/delimited_file_reader.h"
#include "util/file/file_reader.h" #include "util/file/file_reader.h"
#include "util/file/string_file.h"
#include "util/linux/proc_stat_reader.h" #include "util/linux/proc_stat_reader.h"
#include "util/misc/lexing.h" #include "util/misc/lexing.h"
namespace crashpad { namespace crashpad {
ProcessInfo::ProcessInfo() ProcessInfo::ProcessInfo()
: supplementary_groups_(), : connection_(),
supplementary_groups_(),
start_time_(), start_time_(),
pid_(-1), pid_(-1),
ppid_(-1), ppid_(-1),
@ -45,16 +47,19 @@ bool ProcessInfo::InitializeWithPtrace(PtraceConnection* connection) {
INITIALIZATION_STATE_SET_INITIALIZING(initialized_); INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
DCHECK(connection); DCHECK(connection);
connection_ = connection;
pid_ = connection->GetProcessID(); pid_ = connection->GetProcessID();
is_64_bit_ = connection->Is64Bit(); is_64_bit_ = connection->Is64Bit();
{ {
char path[32]; char path[32];
snprintf(path, sizeof(path), "/proc/%d/status", pid_); snprintf(path, sizeof(path), "/proc/%d/status", pid_);
FileReader status_file; std::string contents;
if (!status_file.Open(base::FilePath(path))) { if (!connection->ReadFileContents(base::FilePath(path), &contents)) {
return false; return false;
} }
StringFile status_file;
status_file.SetString(contents);
DelimitedFileReader status_file_line_reader(&status_file); DelimitedFileReader status_file_line_reader(&status_file);
@ -230,7 +235,7 @@ bool ProcessInfo::StartTime(timeval* start_time) const {
if (start_time_initialized_.is_uninitialized()) { if (start_time_initialized_.is_uninitialized()) {
start_time_initialized_.set_invalid(); start_time_initialized_.set_invalid();
ProcStatReader reader; ProcStatReader reader;
if (!reader.Initialize(pid_)) { if (!reader.Initialize(connection_, pid_)) {
return false; return false;
} }
if (!reader.StartTime(&start_time_)) { if (!reader.StartTime(&start_time_)) {
@ -252,10 +257,12 @@ bool ProcessInfo::Arguments(std::vector<std::string>* argv) const {
char path[32]; char path[32];
snprintf(path, sizeof(path), "/proc/%d/cmdline", pid_); snprintf(path, sizeof(path), "/proc/%d/cmdline", pid_);
FileReader cmdline_file; std::string contents;
if (!cmdline_file.Open(base::FilePath(path))) { if (!connection_->ReadFileContents(base::FilePath(path), &contents)) {
return false; return false;
} }
StringFile cmdline_file;
cmdline_file.SetString(contents);
DelimitedFileReader cmdline_file_field_reader(&cmdline_file); DelimitedFileReader cmdline_file_field_reader(&cmdline_file);