internal_linux.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file. 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/process/internal_linux.h" 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <unistd.h> 890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <string> 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <vector> 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/file_util.h" 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/logging.h" 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/string_util.h" 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/strings/string_split.h" 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/threading/thread_restrictions.h" 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace base { 2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace internal { 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kProcDir[] = "/proc"; 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kStatFile[] = "stat"; 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)base::FilePath GetProcPidDir(pid_t pid) { 2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return base::FilePath(kProcDir).Append(IntToString(pid)); 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)pid_t ProcDirSlotToPid(const char* d_name) { 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int i; 3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (i = 0; i < NAME_MAX && d_name[i]; ++i) { 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!IsAsciiDigit(d_name[i])) { 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return 0; 3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (i == NAME_MAX) 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return 0; 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Read the process's command line. 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) pid_t pid; 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string pid_string(d_name); 4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!StringToInt(pid_string, &pid)) { 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) NOTREACHED(); 4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return 0; 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return pid; 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool ReadProcStats(pid_t pid, std::string* buffer) { 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) buffer->clear(); 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Synchronously reading files in /proc is safe. 5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ThreadRestrictions::ScopedAllowIO allow_io; 5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FilePath stat_file = internal::GetProcPidDir(pid).Append(kStatFile); 5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!file_util::ReadFileToString(stat_file, buffer)) { 5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DLOG(WARNING) << "Failed to get process stats."; 5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return false; 5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return !buffer->empty(); 6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool ParseProcStats(const std::string& stats_data, 6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<std::string>* proc_stats) { 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // |stats_data| may be empty if the process disappeared somehow. 6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // e.g. http://crbug.com/145811 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (stats_data.empty()) 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return false; 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // The stat file is formatted as: 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // pid (process name) data1 data2 .... dataN 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Look for the closing paren by scanning backwards, to avoid being fooled by 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // processes with ')' in the name. 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size_t open_parens_idx = stats_data.find(" ("); 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size_t close_parens_idx = stats_data.rfind(") "); 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (open_parens_idx == std::string::npos || 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) close_parens_idx == std::string::npos || 7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) open_parens_idx > close_parens_idx) { 7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DLOG(WARNING) << "Failed to find matched parens in '" << stats_data << "'"; 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) NOTREACHED(); 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return false; 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) open_parens_idx++; 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) proc_stats->clear(); 8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // PID. 8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) proc_stats->push_back(stats_data.substr(0, open_parens_idx)); 8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Process name without parentheses. 8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) proc_stats->push_back( 9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stats_data.substr(open_parens_idx + 1, 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) close_parens_idx - (open_parens_idx + 1))); 9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Split the rest. 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<std::string> other_stats; 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SplitString(stats_data.substr(close_parens_idx + 2), ' ', &other_stats); 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (size_t i = 0; i < other_stats.size(); ++i) 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) proc_stats->push_back(other_stats[i]); 9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return true; 9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int GetProcStatsFieldAsInt(const std::vector<std::string>& proc_stats, 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ProcStatsFields field_num) { 10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_GE(field_num, VM_PPID); 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CHECK_LT(static_cast<size_t>(field_num), proc_stats.size()); 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int value; 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return StringToInt(proc_stats[field_num], &value) ? value : 0; 10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)size_t GetProcStatsFieldAsSizeT(const std::vector<std::string>& proc_stats, 11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ProcStatsFields field_num) { 11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_GE(field_num, VM_PPID); 11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CHECK_LT(static_cast<size_t>(field_num), proc_stats.size()); 11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size_t value; 11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return StringToSizeT(proc_stats[field_num], &value) ? value : 0; 11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int ReadProcStatsAndGetFieldAsInt(pid_t pid, 12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ProcStatsFields field_num) { 12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string stats_data; 12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!ReadProcStats(pid, &stats_data)) 12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return 0; 12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<std::string> proc_stats; 12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!ParseProcStats(stats_data, &proc_stats)) 12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return 0; 12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return GetProcStatsFieldAsInt(proc_stats, field_num); 12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)size_t ReadProcStatsAndGetFieldAsSizeT(pid_t pid, 13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ProcStatsFields field_num) { 13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string stats_data; 13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!ReadProcStats(pid, &stats_data)) 13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return 0; 13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<std::string> proc_stats; 13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!ParseProcStats(stats_data, &proc_stats)) 13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return 0; 13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return GetProcStatsFieldAsSizeT(proc_stats, field_num); 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace internal 14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace base 143