diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-08-24 12:15:48 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-08-28 13:30:04 +0000 |
commit | b014812705fc80bff0a5c120dfcef88f349816dc (patch) | |
tree | 25a2e2d9fa285f1add86aa333389a839f81a39ae /chromium/base/process | |
parent | 9f4560b1027ae06fdb497023cdcaf91b8511fa74 (diff) |
BASELINE: Update Chromium to 68.0.3440.125
Change-Id: I23f19369e01f688e496f5bf179abb521ad73874f
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/base/process')
19 files changed, 288 insertions, 415 deletions
diff --git a/chromium/base/process/launch.h b/chromium/base/process/launch.h index 5ba92182e74..b4530b755a2 100644 --- a/chromium/base/process/launch.h +++ b/chromium/base/process/launch.h @@ -21,41 +21,38 @@ #include "base/strings/string_piece.h" #include "build/build_config.h" -#if defined(OS_POSIX) -#include "base/posix/file_descriptor_shuffle.h" -#elif defined(OS_WIN) +#if defined(OS_WIN) #include <windows.h> -#endif - -#if defined(OS_FUCHSIA) +#elif defined(OS_FUCHSIA) #include <launchpad/launchpad.h> #include <zircon/types.h> #endif +#if defined(OS_POSIX) || defined(OS_FUCHSIA) +#include "base/posix/file_descriptor_shuffle.h" +#endif + namespace base { class CommandLine; #if defined(OS_WIN) typedef std::vector<HANDLE> HandlesToInheritVector; -#endif - -#if defined(OS_FUCHSIA) +#elif defined(OS_FUCHSIA) struct HandleToTransfer { uint32_t id; zx_handle_t handle; }; typedef std::vector<HandleToTransfer> HandlesToTransferVector; -#endif - -#if defined(OS_POSIX) typedef std::vector<std::pair<int, int>> FileHandleMappingVector; -#endif +#elif defined(OS_POSIX) +typedef std::vector<std::pair<int, int>> FileHandleMappingVector; +#endif // defined(OS_WIN) // Options for launching a subprocess that are passed to LaunchProcess(). // The default constructor constructs the object with default options. struct BASE_EXPORT LaunchOptions { -#if defined(OS_POSIX) +#if defined(OS_POSIX) || defined(OS_FUCHSIA) // Delegate to be run in between fork and exec in the subprocess (see // pre_exec_delegate below) class BASE_EXPORT PreExecDelegate { @@ -151,7 +148,11 @@ struct BASE_EXPORT LaunchOptions { // CREATE_BREAKAWAY_FROM_JOB flag which allows it to breakout of the parent // job if any. bool force_breakaway_from_job_ = false; -#else // !defined(OS_WIN) + + // If set to true, permission to bring windows to the foreground is passed to + // the launched process if the current process has such permission. + bool grant_foreground_privilege = false; +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) // Set/unset environment variables. These are applied on top of the parent // process environment. Empty (the default) means to inherit the same // environment. See AlterEnvironment(). @@ -164,6 +165,7 @@ struct BASE_EXPORT LaunchOptions { // Remap file descriptors according to the mapping of src_fd->dest_fd to // propagate FDs into the child process. FileHandleMappingVector fds_to_remap; +#endif // defined(OS_WIN) #if defined(OS_LINUX) // If non-zero, start the process using clone(), using flags as provided. @@ -207,10 +209,10 @@ struct BASE_EXPORT LaunchOptions { // case child process is compromised. // Cannot be combined with the clone flag LP_CLONE_FDIO_NAMESPACE, which is // equivalent to cloning every path. - std::vector<std::string> paths_to_map; + std::vector<FilePath> paths_to_map; #endif // defined(OS_FUCHSIA) -#if defined(OS_POSIX) && !defined(OS_FUCHSIA) +#if defined(OS_POSIX) // If not empty, launch the specified executable instead of // cmdline.GetProgram(). This is useful when it is necessary to pass a custom // argv[0]. @@ -233,14 +235,13 @@ struct BASE_EXPORT LaunchOptions { // inheriting the parent's process group. The pgid of the child process // will be the same as its pid. bool new_process_group = false; -#endif // defined(OS_POSIX) && !defined(OS_FUCHSIA) +#endif // defined(OS_POSIX) #if defined(OS_CHROMEOS) // If non-negative, the specified file descriptor will be set as the launched // process' controlling terminal. int ctrl_terminal_fd = -1; #endif // defined(OS_CHROMEOS) -#endif // !defined(OS_WIN) }; // Launch a process via the command line |cmdline|. @@ -281,7 +282,7 @@ BASE_EXPORT Process LaunchProcess(const string16& cmdline, BASE_EXPORT Process LaunchElevatedProcess(const CommandLine& cmdline, const LaunchOptions& options); -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) // A POSIX-specific version of LaunchProcess that takes an argv array // instead of a CommandLine. Useful for situations where you need to // control the command line arguments directly, but prefer the @@ -293,7 +294,7 @@ BASE_EXPORT Process LaunchProcess(const std::vector<std::string>& argv, // given multimap. Only call this function in a child process where you know // that there aren't any other threads. BASE_EXPORT void CloseSuperfluousFds(const InjectiveMultimap& saved_map); -#endif // defined(OS_POSIX) +#endif // defined(OS_WIN) #if defined(OS_WIN) // Set |job_object|'s JOBOBJECT_EXTENDED_LIMIT_INFORMATION @@ -327,9 +328,7 @@ BASE_EXPORT bool GetAppOutputWithExitCode(const CommandLine& cl, // instead of a CommandLine object. Useful for situations where you need to // control the command line arguments directly. BASE_EXPORT bool GetAppOutput(const StringPiece16& cl, std::string* output); -#endif - -#if defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) // A POSIX-specific version of GetAppOutput that takes an argv array // instead of a CommandLine. Useful for situations where you need to // control the command line arguments directly. @@ -340,7 +339,7 @@ BASE_EXPORT bool GetAppOutput(const std::vector<std::string>& argv, // stderr. BASE_EXPORT bool GetAppOutputAndError(const std::vector<std::string>& argv, std::string* output); -#endif // defined(OS_POSIX) +#endif // defined(OS_WIN) // If supported on the platform, and the user has sufficent rights, increase // the current process's scheduling priority to a high priority. diff --git a/chromium/base/process/launch_fuchsia.cc b/chromium/base/process/launch_fuchsia.cc index d1edc473ede..3bc75809f72 100644 --- a/chromium/base/process/launch_fuchsia.cc +++ b/chromium/base/process/launch_fuchsia.cc @@ -62,7 +62,7 @@ bool GetAppOutputInternal(const CommandLine& cmd_line, return process.WaitForExit(exit_code); } -bool MapPathsToLaunchpad(const std::vector<std::string> paths_to_map, +bool MapPathsToLaunchpad(const std::vector<FilePath>& paths_to_map, launchpad_t* lp) { zx_status_t status; @@ -72,29 +72,30 @@ bool MapPathsToLaunchpad(const std::vector<std::string> paths_to_map, paths_c_str.reserve(paths_to_map.size()); for (size_t paths_idx = 0; paths_idx < paths_to_map.size(); ++paths_idx) { - const std::string& next_path_str = paths_to_map[paths_idx]; - - base::FilePath next_path(next_path_str); - if (!DirectoryExists(next_path)) { - DLOG(ERROR) << "Directory does not exist: " << next_path; + const FilePath& next_path = paths_to_map[paths_idx]; + if (!PathExists(next_path)) { + DLOG(ERROR) << "Path does not exist: " << next_path; return false; } - // Get a Zircon handle to the directory |next_path|. - base::File dir(next_path, base::File::FLAG_OPEN | base::File::FLAG_READ); - base::ScopedPlatformFile scoped_fd(dir.TakePlatformFile()); + File dir(next_path, File::FLAG_OPEN | File::FLAG_READ); + ScopedPlatformFile scoped_fd(dir.TakePlatformFile()); zx_handle_t handles[FDIO_MAX_HANDLES] = {}; uint32_t types[FDIO_MAX_HANDLES] = {}; - status = fdio_transfer_fd(scoped_fd.get(), 0, handles, types); - if (status != ZX_OK) { - ZX_LOG(ERROR, status) << "fdio_transfer_fd"; + zx_status_t num_handles = + fdio_transfer_fd(scoped_fd.get(), 0, handles, types); + // fdio_transfer_fd() returns number of transferred handles, or negative + // error. + if (num_handles <= 0) { + DCHECK_LT(num_handles, 0); + ZX_LOG(ERROR, num_handles) << "fdio_transfer_fd"; return false; } ScopedZxHandle scoped_handle(handles[0]); ignore_result(scoped_fd.release()); // Close the handles that we won't use. - for (int i = 1; i < FDIO_MAX_HANDLES; ++i) { + for (int i = 1; i < num_handles; ++i) { zx_handle_close(handles[i]); } @@ -107,14 +108,14 @@ bool MapPathsToLaunchpad(const std::vector<std::string> paths_to_map, // Add the handle to the child's nametable. // We use the macro PA_HND(..., <index>) to relate the handle to its // position in the nametable, which is stored as an array of path strings - // |paths_c_str|. + // |paths_str|. status = launchpad_add_handle(lp, scoped_handle.release(), PA_HND(PA_NS_DIR, paths_idx)); if (status != ZX_OK) { ZX_LOG(ERROR, status) << "launchpad_add_handle"; return false; } - paths_c_str.push_back(next_path_str.c_str()); + paths_c_str.push_back(next_path.value().c_str()); } if (!paths_c_str.empty()) { @@ -135,8 +136,7 @@ struct LaunchpadScopedTraits { static void Free(launchpad_t* lp) { launchpad_destroy(lp); } }; -using ScopedLaunchpad = - base::ScopedGeneric<launchpad_t*, LaunchpadScopedTraits>; +using ScopedLaunchpad = ScopedGeneric<launchpad_t*, LaunchpadScopedTraits>; } // namespace @@ -193,7 +193,7 @@ Process LaunchProcess(const std::vector<std::string>& argv, environ_modifications["PWD"] = options.current_directory.value(); } else { FilePath cwd; - base::GetCurrentDirectory(&cwd); + GetCurrentDirectory(&cwd); environ_modifications["PWD"] = cwd.value(); } diff --git a/chromium/base/process/launch_win.cc b/chromium/base/process/launch_win.cc index 0c798a88b45..0ae6820dfd9 100644 --- a/chromium/base/process/launch_win.cc +++ b/chromium/base/process/launch_win.cc @@ -20,7 +20,6 @@ #include "base/debug/activity_tracker.h" #include "base/debug/stack_trace.h" #include "base/logging.h" -#include "base/message_loop/message_loop.h" #include "base/metrics/histogram.h" #include "base/process/kill.h" #include "base/strings/utf_string_conversions.h" @@ -256,9 +255,13 @@ Process LaunchProcess(const string16& cmdline, startup_info->hStdError = options.stderr_handle; } - if (options.job_handle) { + const bool launch_suspended = + options.job_handle || options.grant_foreground_privilege; + + if (launch_suspended) flags |= CREATE_SUSPENDED; + if (options.job_handle) { // If this code is run under a debugger, the launched process is // automatically associated with a job object created by the debugger. // The CREATE_BREAKAWAY_FROM_JOB flag is used to prevent this on Windows @@ -307,18 +310,23 @@ Process LaunchProcess(const string16& cmdline, } base::win::ScopedProcessInformation process_info(temp_process_info); - if (options.job_handle) { - if (0 == AssignProcessToJobObject(options.job_handle, - process_info.process_handle())) { - DLOG(ERROR) << "Could not AssignProcessToObject."; - Process scoped_process(process_info.TakeProcessHandle()); - scoped_process.Terminate(win::kProcessKilledExitCode, true); - return Process(); - } + if (options.job_handle && + !AssignProcessToJobObject(options.job_handle, + process_info.process_handle())) { + DPLOG(ERROR) << "Could not AssignProcessToObject"; + Process scoped_process(process_info.TakeProcessHandle()); + scoped_process.Terminate(win::kProcessKilledExitCode, true); + return Process(); + } - ResumeThread(process_info.thread_handle()); + if (options.grant_foreground_privilege && + !AllowSetForegroundWindow(GetProcId(process_info.process_handle()))) { + DPLOG(ERROR) << "Failed to grant foreground privilege to launched process"; } + if (launch_suspended) + ResumeThread(process_info.thread_handle()); + if (options.wait) WaitForSingleObject(process_info.process_handle(), INFINITE); diff --git a/chromium/base/process/process_iterator.cc b/chromium/base/process/process_iterator.cc index 013017f75b5..8b530a067ef 100644 --- a/chromium/base/process/process_iterator.cc +++ b/chromium/base/process/process_iterator.cc @@ -7,7 +7,7 @@ namespace base { -#if defined(OS_POSIX) +#if defined(OS_POSIX) || defined(OS_FUCHSIA) ProcessEntry::ProcessEntry() : pid_(0), ppid_(0), gid_(0) {} ProcessEntry::ProcessEntry(const ProcessEntry& other) = default; ProcessEntry::~ProcessEntry() = default; diff --git a/chromium/base/process/process_iterator.h b/chromium/base/process/process_iterator.h index 54a4ec610cb..b30ad412226 100644 --- a/chromium/base/process/process_iterator.h +++ b/chromium/base/process/process_iterator.h @@ -26,7 +26,7 @@ #include <sys/sysctl.h> #elif defined(OS_FREEBSD) #include <sys/user.h> -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) #include <dirent.h> #endif @@ -38,7 +38,7 @@ struct ProcessEntry : public PROCESSENTRY32 { ProcessId parent_pid() const { return th32ParentProcessID; } const wchar_t* exe_file() const { return szExeFile; } }; -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) struct BASE_EXPORT ProcessEntry { ProcessEntry(); ProcessEntry(const ProcessEntry& other); @@ -58,7 +58,7 @@ struct BASE_EXPORT ProcessEntry { std::string exe_file_; std::vector<std::string> cmd_line_args_; }; -#endif // defined(OS_POSIX) +#endif // defined(OS_WIN) // Used to filter processes by process ID. class ProcessFilter { @@ -112,7 +112,7 @@ class BASE_EXPORT ProcessIterator { #elif defined(OS_MACOSX) || defined(OS_BSD) std::vector<kinfo_proc> kinfo_procs_; size_t index_of_kinfo_proc_; -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) DIR* procfs_dir_; #endif ProcessEntry entry_; diff --git a/chromium/base/process/process_linux.cc b/chromium/base/process/process_linux.cc index 586766e7863..faf39afd4b8 100644 --- a/chromium/base/process/process_linux.cc +++ b/chromium/base/process/process_linux.cc @@ -8,7 +8,6 @@ #include <sys/resource.h> #include "base/files/file_util.h" -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" @@ -75,19 +74,13 @@ struct CGroups { const int kBackgroundPriority = 5; #endif // defined(OS_CHROMEOS) -struct CheckForNicePermission { - CheckForNicePermission() : can_reraise_priority(false) { - // We won't be able to raise the priority if we don't have the right rlimit. - // The limit may be adjusted in /etc/security/limits.conf for PAM systems. - struct rlimit rlim; - if ((getrlimit(RLIMIT_NICE, &rlim) == 0) && - (20 - kForegroundPriority) <= static_cast<int>(rlim.rlim_cur)) { - can_reraise_priority = true; - } - }; - - bool can_reraise_priority; -}; +bool CanReraisePriority() { + // We won't be able to raise the priority if we don't have the right rlimit. + // The limit may be adjusted in /etc/security/limits.conf for PAM systems. + struct rlimit rlim; + return (getrlimit(RLIMIT_NICE, &rlim) == 0) && + (20 - kForegroundPriority) <= static_cast<int>(rlim.rlim_cur); +} } // namespace @@ -98,9 +91,8 @@ bool Process::CanBackgroundProcesses() { return true; #endif // defined(OS_CHROMEOS) - static LazyInstance<CheckForNicePermission>::DestructorAtExit - check_for_nice_permission = LAZY_INSTANCE_INITIALIZER; - return check_for_nice_permission.Get().can_reraise_priority; + static const bool can_reraise_priority = CanReraisePriority(); + return can_reraise_priority; } bool Process::IsProcessBackgrounded() const { diff --git a/chromium/base/process/process_metrics.cc b/chromium/base/process/process_metrics.cc index 2eff3ea3d0c..c3a70633a3f 100644 --- a/chromium/base/process/process_metrics.cc +++ b/chromium/base/process/process_metrics.cc @@ -97,6 +97,32 @@ std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateCurrentProcessMetrics() { #endif // !defined(OS_MACOSX) || defined(OS_IOS) } +#if !defined(OS_FREEBSD) || !defined(OS_POSIX) +double ProcessMetrics::GetPlatformIndependentCPUUsage() { + TimeDelta cumulative_cpu = GetCumulativeCPUUsage(); + TimeTicks time = TimeTicks::Now(); + + if (last_cumulative_cpu_.is_zero()) { + // First call, just set the last values. + last_cumulative_cpu_ = cumulative_cpu; + last_cpu_time_ = time; + return 0; + } + + TimeDelta system_time_delta = cumulative_cpu - last_cumulative_cpu_; + TimeDelta time_delta = time - last_cpu_time_; + DCHECK(!time_delta.is_zero()); + if (time_delta.is_zero()) + return 0; + + last_cumulative_cpu_ = cumulative_cpu; + last_cpu_time_ = time; + + return 100.0 * system_time_delta.InMicrosecondsF() / + time_delta.InMicrosecondsF(); +} +#endif + #if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX) int ProcessMetrics::CalculateIdleWakeupsPerSecond( uint64_t absolute_idle_wakeups) { diff --git a/chromium/base/process/process_metrics.h b/chromium/base/process/process_metrics.h index 3ae373f6963..0170a0c2db9 100644 --- a/chromium/base/process/process_metrics.h +++ b/chromium/base/process/process_metrics.h @@ -143,6 +143,12 @@ class BASE_EXPORT ProcessMetrics { // first call, and an actual value only on the second and subsequent calls. double GetPlatformIndependentCPUUsage(); + // Returns the cumulative CPU usage across all threads of the process since + // process start. In case of multi-core processors, a process can consume CPU + // at a rate higher than wall-clock time, e.g. two cores at full utilization + // will result in a time delta of 2 seconds/per 1 wall-clock second. + TimeDelta GetCumulativeCPUUsage(); + // Returns the number of average idle cpu wakeups per second since the last // call. int GetIdleWakeupsPerSecond(); @@ -219,8 +225,8 @@ class BASE_EXPORT ProcessMetrics { // Used to store the previous times and CPU usage counts so we can // compute the CPU usage between calls. TimeTicks last_cpu_time_; -#if defined(OS_WIN) || defined(OS_MACOSX) - int64_t last_system_time_; +#if !defined(OS_FREEBSD) || !defined(OS_POSIX) + TimeDelta last_cumulative_cpu_; #endif #if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX) @@ -241,10 +247,7 @@ class BASE_EXPORT ProcessMetrics { mach_port_t TaskForPid(ProcessHandle process) const; PortProvider* port_provider_; -#elif defined(OS_POSIX) - // Jiffie count at the last_cpu_time_ we updated. - int last_cpu_; -#endif // defined(OS_POSIX) +#endif // defined(OS_MACOSX) #endif // !defined(OS_IOS) DISALLOW_COPY_AND_ASSIGN(ProcessMetrics); @@ -265,10 +268,11 @@ BASE_EXPORT size_t GetPageSize(); BASE_EXPORT size_t GetMaxFds(); #if defined(OS_POSIX) && !defined(OS_FUCHSIA) -// Sets the file descriptor soft limit to |max_descriptors| or the OS hard -// limit, whichever is lower. -BASE_EXPORT void SetFdLimit(unsigned int max_descriptors); -#endif // defined(OS_POSIX) +// Increases the file descriptor soft limit to |max_descriptors| or the OS hard +// limit, whichever is lower. If the limit is already higher than +// |max_descriptors|, then nothing happens. +BASE_EXPORT void IncreaseFdLimitTo(unsigned int max_descriptors); +#endif // defined(OS_POSIX) && !defined(OS_FUCHSIA) #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \ defined(OS_ANDROID) || defined(OS_AIX) || defined(OS_FUCHSIA) diff --git a/chromium/base/process/process_metrics_freebsd.cc b/chromium/base/process/process_metrics_freebsd.cc index 4dee9980292..a552c033dd8 100644 --- a/chromium/base/process/process_metrics_freebsd.cc +++ b/chromium/base/process/process_metrics_freebsd.cc @@ -12,6 +12,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/process/process_metrics_iocounters.h" +#include "base/stl_util.h" namespace base { @@ -27,15 +28,20 @@ std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics( double ProcessMetrics::GetPlatformIndependentCPUUsage() { struct kinfo_proc info; - int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process_ }; + int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, process_}; size_t length = sizeof(info); - if (sysctl(mib, arraysize(mib), &info, &length, NULL, 0) < 0) + if (sysctl(mib, base::size(mib), &info, &length, NULL, 0) < 0) return 0; return (info.ki_pctcpu / FSCALE) * 100.0; } +TimeDelta ProcessMetrics::GetCumulativeCPUUsage() { + NOTREACHED(); + return TimeDelta(); +} + bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const { return false; } @@ -45,7 +51,7 @@ size_t GetSystemCommitCharge() { unsigned long mem_total, mem_free, mem_inactive; size_t length = sizeof(mem_total); - if (sysctl(mib, arraysize(mib), &mem_total, &length, NULL, 0) < 0) + if (sysctl(mib, base::size(mib), &mem_total, &length, NULL, 0) < 0) return 0; length = sizeof(mem_free); diff --git a/chromium/base/process/process_metrics_fuchsia.cc b/chromium/base/process/process_metrics_fuchsia.cc index 3710c308408..a34dff73150 100644 --- a/chromium/base/process/process_metrics_fuchsia.cc +++ b/chromium/base/process/process_metrics_fuchsia.cc @@ -25,9 +25,9 @@ std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics( return nullptr; } -double ProcessMetrics::GetPlatformIndependentCPUUsage() { +TimeDelta ProcessMetrics::GetCumulativeCPUUsage() { NOTIMPLEMENTED(); // TODO(fuchsia): https://crbug.com/706592. - return 0.0; + return TimeDelta(); } bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) { diff --git a/chromium/base/process/process_metrics_ios.cc b/chromium/base/process/process_metrics_ios.cc index 794304f7658..83fc3d69331 100644 --- a/chromium/base/process/process_metrics_ios.cc +++ b/chromium/base/process/process_metrics_ios.cc @@ -25,9 +25,9 @@ std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics( return WrapUnique(new ProcessMetrics(process)); } -double ProcessMetrics::GetPlatformIndependentCPUUsage() { +TimeDelta ProcessMetrics::GetCumulativeCPUUsage() { NOTIMPLEMENTED(); - return 0; + return TimeDelta(); } size_t GetMaxFds() { @@ -47,7 +47,7 @@ size_t GetMaxFds() { return static_cast<size_t>(max_fds); } -void SetFdLimit(unsigned int max_descriptors) { +void IncreaseFdLimitTo(unsigned int max_descriptors) { // Unimplemented. } diff --git a/chromium/base/process/process_metrics_linux.cc b/chromium/base/process/process_metrics_linux.cc index e13f9e7a643..16cde35368a 100644 --- a/chromium/base/process/process_metrics_linux.cc +++ b/chromium/base/process/process_metrics_linux.cc @@ -132,35 +132,17 @@ bool ReadProcStatusAndGetFieldAsUint64(pid_t pid, // Get the total CPU of a single process. Return value is number of jiffies // on success or -1 on error. -int GetProcessCPU(pid_t pid) { - // Use /proc/<pid>/task to find all threads and parse their /stat file. - FilePath task_path = internal::GetProcPidDir(pid).Append("task"); - - DIR* dir = opendir(task_path.value().c_str()); - if (!dir) { - DPLOG(ERROR) << "opendir(" << task_path.value() << ")"; +int64_t GetProcessCPU(pid_t pid) { + std::string buffer; + std::vector<std::string> proc_stats; + if (!internal::ReadProcStats(pid, &buffer) || + !internal::ParseProcStats(buffer, &proc_stats)) { return -1; } - int total_cpu = 0; - while (struct dirent* ent = readdir(dir)) { - pid_t tid = internal::ProcDirSlotToPid(ent->d_name); - if (!tid) - continue; - - // Synchronously reading files in /proc does not hit the disk. - ThreadRestrictions::ScopedAllowIO allow_io; - - std::string stat; - FilePath stat_path = - task_path.Append(ent->d_name).Append(internal::kStatFile); - if (ReadFileToString(stat_path, &stat)) { - int cpu = ParseProcStatCPU(stat); - if (cpu > 0) - total_cpu += cpu; - } - } - closedir(dir); + int64_t total_cpu = + internal::GetProcStatsFieldAsInt64(proc_stats, internal::VM_UTIME) + + internal::GetProcStatsFieldAsInt64(proc_stats, internal::VM_STIME); return total_cpu; } @@ -216,46 +198,8 @@ size_t ProcessMetrics::GetResidentSetSize() const { getpagesize(); } -double ProcessMetrics::GetPlatformIndependentCPUUsage() { - TimeTicks time = TimeTicks::Now(); - - if (last_cpu_ == 0) { - // First call, just set the last values. - last_cpu_time_ = time; - last_cpu_ = GetProcessCPU(process_); - return 0.0; - } - - TimeDelta time_delta = time - last_cpu_time_; - if (time_delta.is_zero()) { - NOTREACHED(); - return 0.0; - } - - int cpu = GetProcessCPU(process_); - - // The number of jiffies in the time period. Convert to percentage. - // Note: this means this will go *over* 100 in the case where multiple threads - // are together adding to more than one CPU's worth. - TimeDelta cpu_time = internal::ClockTicksToTimeDelta(cpu); - TimeDelta last_cpu_time = internal::ClockTicksToTimeDelta(last_cpu_); - - // If the number of threads running in the process has decreased since the - // last time this function was called, |last_cpu_time| will be greater than - // |cpu_time| which will result in a negative value in the below percentage - // calculation. Prevent this by clamping to 0. https://crbug.com/546565. - // This computation is known to be shaky when threads are destroyed between - // "last" and "now", but for our current purposes, it's all right. - double percentage = 0.0; - if (last_cpu_time < cpu_time) { - percentage = 100.0 * (cpu_time - last_cpu_time).InSecondsF() / - time_delta.InSecondsF(); - } - - last_cpu_time_ = time; - last_cpu_ = cpu; - - return percentage; +TimeDelta ProcessMetrics::GetCumulativeCPUUsage() { + return internal::ClockTicksToTimeDelta(GetProcessCPU(process_)); } // For the /proc/self/io file to exist, the Linux kernel must have @@ -356,13 +300,12 @@ int ProcessMetrics::GetOpenFdSoftLimit() const { return -1; } -ProcessMetrics::ProcessMetrics(ProcessHandle process) - : process_(process), #if defined(OS_LINUX) || defined(OS_AIX) - last_absolute_idle_wakeups_(0), +ProcessMetrics::ProcessMetrics(ProcessHandle process) + : process_(process), last_absolute_idle_wakeups_(0) {} +#else +ProcessMetrics::ProcessMetrics(ProcessHandle process) : process_(process) {} #endif - last_cpu_(0) { -} #if defined(OS_CHROMEOS) // Private, Shared and Proportional working set sizes are obtained from diff --git a/chromium/base/process/process_metrics_mac.cc b/chromium/base/process/process_metrics_mac.cc index 148253f26d2..4ecf8cf1472 100644 --- a/chromium/base/process/process_metrics_mac.cc +++ b/chromium/base/process/process_metrics_mac.cc @@ -127,10 +127,10 @@ ProcessMetrics::TaskVMInfo ProcessMetrics::GetTaskVMInfo() const { (r)->tv_usec = (a)->microseconds; \ } while (0) -double ProcessMetrics::GetPlatformIndependentCPUUsage() { +TimeDelta ProcessMetrics::GetCumulativeCPUUsage() { mach_port_t task = TaskForPid(process_); if (task == MACH_PORT_NULL) - return 0; + return TimeDelta(); // Libtop explicitly loops over the threads (libtop_pinfo_update_cpu_usage() // in libtop.c), but this is more concise and gives the same results: @@ -142,12 +142,12 @@ double ProcessMetrics::GetPlatformIndependentCPUUsage() { &thread_info_count); if (kr != KERN_SUCCESS) { // Most likely cause: |task| is a zombie. - return 0; + return TimeDelta(); } task_basic_info_64 task_info_data; if (!GetTaskInfo(task, &task_info_data)) - return 0; + return TimeDelta(); /* Set total_time. */ // thread info contains live time... @@ -162,26 +162,7 @@ double ProcessMetrics::GetPlatformIndependentCPUUsage() { timeradd(&user_timeval, &task_timeval, &task_timeval); timeradd(&system_timeval, &task_timeval, &task_timeval); - TimeTicks time = TimeTicks::Now(); - int64_t task_time = TimeValToMicroseconds(task_timeval); - - if (last_system_time_ == 0) { - // First call, just set the last values. - last_cpu_time_ = time; - last_system_time_ = task_time; - return 0; - } - - int64_t system_time_delta = task_time - last_system_time_; - int64_t time_delta = (time - last_cpu_time_).InMicroseconds(); - DCHECK_NE(0U, time_delta); - if (time_delta == 0) - return 0; - - last_cpu_time_ = time; - last_system_time_ = task_time; - - return static_cast<double>(system_time_delta * 100.0) / time_delta; + return TimeDelta::FromMicroseconds(TimeValToMicroseconds(task_timeval)); } int ProcessMetrics::GetPackageIdleWakeupsPerSecond() { @@ -220,7 +201,6 @@ bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const { ProcessMetrics::ProcessMetrics(ProcessHandle process, PortProvider* port_provider) : process_(process), - last_system_time_(0), last_absolute_idle_wakeups_(0), last_absolute_package_idle_wakeups_(0), port_provider_(port_provider) {} diff --git a/chromium/base/process/process_metrics_openbsd.cc b/chromium/base/process/process_metrics_openbsd.cc index 3bb1ac5c3bb..509ed0b28ab 100644 --- a/chromium/base/process/process_metrics_openbsd.cc +++ b/chromium/base/process/process_metrics_openbsd.cc @@ -45,29 +45,25 @@ static int GetProcessCPU(pid_t pid) { double ProcessMetrics::GetPlatformIndependentCPUUsage() { TimeTicks time = TimeTicks::Now(); - if (last_cpu_ == 0) { + if (last_cpu_time_.is_zero()) { // First call, just set the last values. last_cpu_time_ = time; - last_cpu_ = GetProcessCPU(process_); return 0; } - int64_t time_delta = (time - last_cpu_time_).InMicroseconds(); - DCHECK_NE(time_delta, 0); - - if (time_delta == 0) - return 0; - int cpu = GetProcessCPU(process_); last_cpu_time_ = time; - last_cpu_ = cpu; - double percentage = static_cast<double>((cpu * 100.0) / FSCALE); return percentage; } +TimeDelta ProcessMetrics::GetCumulativeCPUUsage() { + NOTREACHED(); + return TimeDelta(); +} + ProcessMetrics::ProcessMetrics(ProcessHandle process) : process_(process), last_cpu_(0) {} diff --git a/chromium/base/process/process_metrics_posix.cc b/chromium/base/process/process_metrics_posix.cc index e2d2c62e1e5..a09bbf2c56e 100644 --- a/chromium/base/process/process_metrics_posix.cc +++ b/chromium/base/process/process_metrics_posix.cc @@ -71,11 +71,12 @@ size_t GetMaxFds() { return static_cast<size_t>(max_fds); } - -void SetFdLimit(unsigned int max_descriptors) { +void IncreaseFdLimitTo(unsigned int max_descriptors) { struct rlimit limits; if (getrlimit(RLIMIT_NOFILE, &limits) == 0) { unsigned int new_limit = max_descriptors; + if (max_descriptors <= limits.rlim_cur) + return; if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) { new_limit = limits.rlim_max; } diff --git a/chromium/base/process/process_metrics_unittest.cc b/chromium/base/process/process_metrics_unittest.cc index cb952950286..eba543a6187 100644 --- a/chromium/base/process/process_metrics_unittest.cc +++ b/chromium/base/process/process_metrics_unittest.cc @@ -33,7 +33,7 @@ namespace base { namespace debug { -#if defined(OS_LINUX) || defined(OS_CHROMEOS) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN) namespace { void BusyWork(std::vector<std::string>* vec) { @@ -321,7 +321,7 @@ TEST_F(SystemMetricsTest, ParseVmstat) { } #endif // defined(OS_LINUX) || defined(OS_ANDROID) -#if defined(OS_LINUX) || defined(OS_CHROMEOS) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN) // Test that ProcessMetrics::GetPlatformIndependentCPUUsage() doesn't return // negative values when the number of threads running on the process decreases @@ -352,15 +352,25 @@ TEST_F(SystemMetricsTest, TestNoNegativeCpuUsage) { thread2.task_runner()->PostTask(FROM_HERE, BindOnce(&BusyWork, &vec2)); thread3.task_runner()->PostTask(FROM_HERE, BindOnce(&BusyWork, &vec3)); + TimeDelta prev_cpu_usage = metrics->GetCumulativeCPUUsage(); + EXPECT_GE(prev_cpu_usage, TimeDelta()); EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0); thread1.Stop(); + TimeDelta current_cpu_usage = metrics->GetCumulativeCPUUsage(); + EXPECT_GE(current_cpu_usage, prev_cpu_usage); + prev_cpu_usage = current_cpu_usage; EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0); thread2.Stop(); + current_cpu_usage = metrics->GetCumulativeCPUUsage(); + EXPECT_GE(current_cpu_usage, prev_cpu_usage); + prev_cpu_usage = current_cpu_usage; EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0); thread3.Stop(); + current_cpu_usage = metrics->GetCumulativeCPUUsage(); + EXPECT_GE(current_cpu_usage, prev_cpu_usage); EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0); } diff --git a/chromium/base/process/process_metrics_win.cc b/chromium/base/process/process_metrics_win.cc index faabdbf63a2..18ef58a725c 100644 --- a/chromium/base/process/process_metrics_win.cc +++ b/chromium/base/process/process_metrics_win.cc @@ -128,14 +128,7 @@ class WorkingSetInformationBuffer { } // namespace -static uint64_t FileTimeToUTC(const FILETIME& ftime) { - LARGE_INTEGER li; - li.LowPart = ftime.dwLowDateTime; - li.HighPart = ftime.dwHighDateTime; - return li.QuadPart; -} - -double ProcessMetrics::GetPlatformIndependentCPUUsage() { +TimeDelta ProcessMetrics::GetCumulativeCPUUsage() { FILETIME creation_time; FILETIME exit_time; FILETIME kernel_time; @@ -146,37 +139,18 @@ double ProcessMetrics::GetPlatformIndependentCPUUsage() { // We don't assert here because in some cases (such as in the Task Manager) // we may call this function on a process that has just exited but we have // not yet received the notification. - return 0; - } - int64_t system_time = FileTimeToUTC(kernel_time) + FileTimeToUTC(user_time); - TimeTicks time = TimeTicks::Now(); - - if (last_system_time_ == 0) { - // First call, just set the last values. - last_system_time_ = system_time; - last_cpu_time_ = time; - return 0; + return TimeDelta(); } - int64_t system_time_delta = system_time - last_system_time_; - // FILETIME is in 100-nanosecond units, so this needs microseconds times 10. - int64_t time_delta = (time - last_cpu_time_).InMicroseconds() * 10; - DCHECK_NE(0U, time_delta); - if (time_delta == 0) - return 0; - - - last_system_time_ = system_time; - last_cpu_time_ = time; - - return static_cast<double>(system_time_delta * 100) / time_delta; + return TimeDelta::FromFileTime(kernel_time) + + TimeDelta::FromFileTime(user_time); } bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const { return GetProcessIoCounters(process_.Get(), io_counters) != FALSE; } -ProcessMetrics::ProcessMetrics(ProcessHandle process) : last_system_time_(0) { +ProcessMetrics::ProcessMetrics(ProcessHandle process) { if (process) { HANDLE duplicate_handle = INVALID_HANDLE_VALUE; BOOL result = ::DuplicateHandle(::GetCurrentProcess(), process, diff --git a/chromium/base/process/process_unittest.cc b/chromium/base/process/process_unittest.cc index f5058ebc504..9f678d141a1 100644 --- a/chromium/base/process/process_unittest.cc +++ b/chromium/base/process/process_unittest.cc @@ -146,7 +146,7 @@ TEST_F(ProcessTest, Terminate) { EXPECT_NE(TERMINATION_STATUS_STILL_RUNNING, GetTerminationStatus(process.Handle(), &exit_code)); -#if !defined(OS_POSIX) +#if !defined(OS_POSIX) && !defined(OS_FUCHSIA) // The POSIX implementation actually ignores the exit_code. EXPECT_EQ(kExpectedExitCode, exit_code); #endif diff --git a/chromium/base/process/process_util_unittest.cc b/chromium/base/process/process_util_unittest.cc index a2a5e9fc553..89466695fcf 100644 --- a/chromium/base/process/process_util_unittest.cc +++ b/chromium/base/process/process_util_unittest.cc @@ -9,7 +9,6 @@ #include <limits> -#include "base/base_paths_fuchsia.h" #include "base/command_line.h" #include "base/debug/alias.h" #include "base/debug/stack_trace.h" @@ -44,14 +43,14 @@ #include <sys/syscall.h> #endif #if defined(OS_POSIX) +#include <sys/resource.h> +#endif +#if defined(OS_POSIX) || defined(OS_FUCHSIA) #include <dlfcn.h> #include <errno.h> #include <fcntl.h> #include <sched.h> #include <signal.h> -#if !defined(OS_FUCHSIA) -#include <sys/resource.h> -#endif #include <sys/socket.h> #include <sys/types.h> #include <sys/wait.h> @@ -72,6 +71,7 @@ #include <zircon/process.h> #include <zircon/processargs.h> #include <zircon/syscalls.h> +#include "base/base_paths_fuchsia.h" #endif namespace base { @@ -80,24 +80,20 @@ namespace { const char kSignalFileSlow[] = "SlowChildProcess.die"; const char kSignalFileKill[] = "KilledChildProcess.die"; +const char kTestHelper[] = "test_child_process"; -#if defined(OS_POSIX) +#if defined(OS_POSIX) || defined(OS_FUCHSIA) const char kSignalFileTerm[] = "TerminatedChildProcess.die"; +#endif -#if defined(OS_ANDROID) -const char kShellPath[] = "/system/bin/sh"; -#elif defined(OS_FUCHSIA) -const char kShellPath[] = "/boot/bin/sh"; -const char kSignalFileClone[] = "/tmp/ClonedTmpDir.die"; -#else -const char kShellPath[] = "/bin/sh"; +#if defined(OS_FUCHSIA) +const char kSignalFileClone[] = "ClonedTmpDir.die"; #endif -#endif // defined(OS_POSIX) #if defined(OS_WIN) const int kExpectedStillRunningExitCode = 0x102; const int kExpectedKilledExitCode = 1; -#else +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) const int kExpectedStillRunningExitCode = 0; #endif @@ -144,23 +140,31 @@ const int kSuccess = 0; class ProcessUtilTest : public MultiProcessTest { public: -#if defined(OS_POSIX) + void SetUp() override { + ASSERT_TRUE(PathService::Get(DIR_ASSETS, &test_helper_path_)); + test_helper_path_ = test_helper_path_.AppendASCII(kTestHelper); + } + +#if defined(OS_POSIX) || defined(OS_FUCHSIA) // Spawn a child process that counts how many file descriptors are open. int CountOpenFDsInChild(); #endif // Converts the filename to a platform specific filepath. // On Android files can not be created in arbitrary directories. static std::string GetSignalFilePath(const char* filename); + + protected: + base::FilePath test_helper_path_; }; std::string ProcessUtilTest::GetSignalFilePath(const char* filename) { -#if !defined(OS_ANDROID) - return filename; -#else +#if defined(OS_ANDROID) || defined(OS_FUCHSIA) FilePath tmp_dir; - PathService::Get(DIR_CACHE, &tmp_dir); + PathService::Get(DIR_TEMP, &tmp_dir); tmp_dir = tmp_dir.Append(filename); return tmp_dir.value(); +#else + return filename; #endif } @@ -238,17 +242,12 @@ MULTIPROCESS_TEST_MAIN(CheckTmpFileExists) { } TEST_F(ProcessUtilTest, SelectivelyClonedDir) { - // Selective cloning only works if the test executable is deployed as a - // package. - if (GetPackageRoot().empty()) - return; - const std::string signal_file = ProcessUtilTest::GetSignalFilePath(kSignalFileClone); remove(signal_file.c_str()); LaunchOptions options; - options.paths_to_map.push_back("/tmp"); + options.paths_to_map.push_back(base::FilePath("/tmp")); options.clone_flags = LP_CLONE_FDIO_STDIO; Process process(SpawnChildWithOptions("CheckTmpFileExists", options)); @@ -265,18 +264,13 @@ TEST_F(ProcessUtilTest, SelectivelyClonedDir) { // error code if it detects a directory other than "/tmp", so we can use that as // a signal that it successfully detected another entry in the root namespace. TEST_F(ProcessUtilTest, CloneAlternateDir) { - // Selective cloning only works if the test executable is deployed as a - // package. - if (GetPackageRoot().empty()) - return; - const std::string signal_file = ProcessUtilTest::GetSignalFilePath(kSignalFileClone); remove(signal_file.c_str()); LaunchOptions options; - options.paths_to_map.push_back("/tmp"); - options.paths_to_map.push_back("/data"); + options.paths_to_map.push_back(base::FilePath("/tmp")); + options.paths_to_map.push_back(base::FilePath("/data")); options.clone_flags = LP_CLONE_FDIO_STDIO; Process process(SpawnChildWithOptions("CheckTmpFileExists", options)); @@ -289,7 +283,7 @@ TEST_F(ProcessUtilTest, CloneAlternateDir) { EXPECT_EQ(1, exit_code); } -#endif +#endif // defined(OS_FUCHSIA) // On Android SpawnProcess() doesn't use LaunchProcess() and doesn't support // LaunchOptions::current_directory. @@ -357,7 +351,7 @@ const char kSignalFileCrash[] = "CrashingChildProcess.die"; MULTIPROCESS_TEST_MAIN(CrashingChildProcess) { WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileCrash).c_str()); -#if defined(OS_POSIX) +#if defined(OS_POSIX) || defined(OS_FUCHSIA) // Have to disable to signal handler for segv so we can get a crash // instead of an abnormal termination through the crash dump handler. ::signal(SIGSEGV, SIG_DFL); @@ -395,7 +389,7 @@ TEST_F(ProcessUtilTest, MAYBE_GetTerminationStatusCrash) { #if defined(OS_WIN) EXPECT_EQ(static_cast<int>(0xc0000005), exit_code); -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) int signaled = WIFSIGNALED(exit_code); EXPECT_NE(0, signaled); int signal = WTERMSIG(exit_code); @@ -414,21 +408,21 @@ MULTIPROCESS_TEST_MAIN(KilledChildProcess) { // Kill ourselves. HANDLE handle = ::OpenProcess(PROCESS_ALL_ACCESS, 0, ::GetCurrentProcessId()); ::TerminateProcess(handle, kExpectedKilledExitCode); -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) // Send a SIGKILL to this process, just like the OOM killer would. ::kill(getpid(), SIGKILL); #endif return 1; } -#if defined(OS_POSIX) +#if defined(OS_POSIX) || defined(OS_FUCHSIA) MULTIPROCESS_TEST_MAIN(TerminatedChildProcess) { WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileTerm).c_str()); // Send a SIGTERM to this process. ::kill(getpid(), SIGTERM); return 1; } -#endif // defined(OS_POSIX) +#endif // defined(OS_POSIX) || defined(OS_FUCHSIA) TEST_F(ProcessUtilTest, GetTerminationStatusSigKill) { const std::string signal_file = @@ -454,7 +448,7 @@ TEST_F(ProcessUtilTest, GetTerminationStatusSigKill) { #if defined(OS_WIN) EXPECT_EQ(kExpectedKilledExitCode, exit_code); -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) int signaled = WIFSIGNALED(exit_code); EXPECT_NE(0, signaled); int signal = WTERMSIG(exit_code); @@ -463,7 +457,7 @@ TEST_F(ProcessUtilTest, GetTerminationStatusSigKill) { remove(signal_file.c_str()); } -#if defined(OS_POSIX) +#if defined(OS_POSIX) || defined(OS_FUCHSIA) TEST_F(ProcessUtilTest, GetTerminationStatusSigTerm) { const std::string signal_file = ProcessUtilTest::GetSignalFilePath(kSignalFileTerm); @@ -488,7 +482,7 @@ TEST_F(ProcessUtilTest, GetTerminationStatusSigTerm) { EXPECT_EQ(SIGTERM, signal); remove(signal_file.c_str()); } -#endif // defined(OS_POSIX) +#endif // defined(OS_POSIX) || defined(OS_FUCHSIA) TEST_F(ProcessUtilTest, EnsureTerminationUndying) { test::ScopedTaskEnvironment task_environment; @@ -533,36 +527,6 @@ MULTIPROCESS_TEST_MAIN(process_util_test_die_immediately) { #if defined(OS_WIN) // TODO(estade): if possible, port this test. -TEST_F(ProcessUtilTest, GetAppOutput) { - // Let's create a decently long message. - std::string message; - for (int i = 0; i < 1025; i++) { // 1025 so it does not end on a kilo-byte - // boundary. - message += "Hello!"; - } - // cmd.exe's echo always adds a \r\n to its output. - std::string expected(message); - expected += "\r\n"; - - FilePath cmd(L"cmd.exe"); - CommandLine cmd_line(cmd); - cmd_line.AppendArg("/c"); - cmd_line.AppendArg("echo " + message + ""); - std::string output; - ASSERT_TRUE(GetAppOutput(cmd_line, &output)); - EXPECT_EQ(expected, output); - - // Let's make sure stderr is ignored. - CommandLine other_cmd_line(cmd); - other_cmd_line.AppendArg("/c"); - // http://msdn.microsoft.com/library/cc772622.aspx - cmd_line.AppendArg("echo " + message + " >&2"); - output.clear(); - ASSERT_TRUE(GetAppOutput(other_cmd_line, &output)); - EXPECT_EQ("", output); -} - -// TODO(estade): if possible, port this test. TEST_F(ProcessUtilTest, LaunchAsUser) { UserTokenHandle token; ASSERT_TRUE(OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token)); @@ -615,7 +579,55 @@ TEST_F(ProcessUtilTest, InheritSpecifiedHandles) { } #endif // defined(OS_WIN) -#if defined(OS_POSIX) +TEST_F(ProcessUtilTest, GetAppOutput) { + base::CommandLine command(test_helper_path_); + command.AppendArg("hello"); + command.AppendArg("there"); + command.AppendArg("good"); + command.AppendArg("people"); + std::string output; + EXPECT_TRUE(GetAppOutput(command, &output)); + EXPECT_EQ("hello there good people", output); + output.clear(); + + const char* kEchoMessage = "blah"; + command = base::CommandLine(test_helper_path_); + command.AppendArg("-x"); + command.AppendArg("28"); + command.AppendArg(kEchoMessage); + EXPECT_FALSE(GetAppOutput(command, &output)); + EXPECT_EQ(kEchoMessage, output); +} + +TEST_F(ProcessUtilTest, GetAppOutputWithExitCode) { + const char* kEchoMessage1 = "doge"; + int exit_code = -1; + base::CommandLine command(test_helper_path_); + command.AppendArg(kEchoMessage1); + std::string output; + EXPECT_TRUE(GetAppOutputWithExitCode(command, &output, &exit_code)); + EXPECT_EQ(kEchoMessage1, output); + EXPECT_EQ(0, exit_code); + output.clear(); + + const char* kEchoMessage2 = "pupper"; + const int kExpectedExitCode = 42; + command = base::CommandLine(test_helper_path_); + command.AppendArg("-x"); + command.AppendArg(base::IntToString(kExpectedExitCode)); + command.AppendArg(kEchoMessage2); +#if defined(OS_WIN) + // On Windows, anything that quits with a nonzero status code is handled as a + // "crash", so just ignore GetAppOutputWithExitCode's return value. + GetAppOutputWithExitCode(command, &output, &exit_code); +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) + EXPECT_TRUE(GetAppOutputWithExitCode(command, &output, &exit_code)); +#endif + EXPECT_EQ(kEchoMessage2, output); + EXPECT_EQ(kExpectedExitCode, exit_code); +} + +#if defined(OS_POSIX) || defined(OS_FUCHSIA) namespace { @@ -638,7 +650,7 @@ int GetMaxFilesOpenInProcess() { } return rlim.rlim_cur; -#endif // !defined(OS_FUCHSIA) +#endif // defined(OS_FUCHSIA) } const int kChildPipe = 20; // FD # for write end of pipe in child process. @@ -863,9 +875,8 @@ TEST_F(ProcessUtilTest, FDRemappingIncludesStdio) { EXPECT_EQ(0, exit_code); } -// TODO(https://crbug.com/793412): Disable on Debug/component builds due to -// process launch taking too long and triggering timeouts. -#if defined(OS_FUCHSIA) && defined(NDEBUG) +#if defined(OS_FUCHSIA) + const uint16_t kStartupHandleId = 43; MULTIPROCESS_TEST_MAIN(ProcessUtilsVerifyHandle) { zx_handle_t handle = @@ -920,7 +931,8 @@ TEST_F(ProcessUtilTest, LaunchWithHandleTransfer) { &exit_code)); EXPECT_EQ(0, exit_code); } -#endif // defined(OS_FUCHSIA) && defined(NDEBUG) + +#endif // defined(OS_FUCHSIA) namespace { @@ -964,132 +976,54 @@ const char kLargeString[] = } // namespace TEST_F(ProcessUtilTest, LaunchProcess) { - EnvironmentMap env_changes; - std::vector<std::string> echo_base_test; - echo_base_test.emplace_back(kShellPath); - echo_base_test.emplace_back("-c"); - echo_base_test.emplace_back("echo $BASE_TEST"); - - std::vector<std::string> print_env; - print_env.emplace_back("/usr/bin/env"); const int no_clone_flags = 0; const bool no_clear_environ = false; - const char kBaseTest[] = "BASE_TEST"; + const std::vector<std::string> kPrintEnvCommand = {test_helper_path_.value(), + "-e", kBaseTest}; + EnvironmentMap env_changes; env_changes[kBaseTest] = "bar"; - EXPECT_EQ("bar\n", - TestLaunchProcess( - echo_base_test, env_changes, no_clear_environ, no_clone_flags)); + EXPECT_EQ("bar", TestLaunchProcess(kPrintEnvCommand, env_changes, + no_clear_environ, no_clone_flags)); env_changes.clear(); EXPECT_EQ(0, setenv(kBaseTest, "testing", 1 /* override */)); - EXPECT_EQ("testing\n", - TestLaunchProcess( - echo_base_test, env_changes, no_clear_environ, no_clone_flags)); + EXPECT_EQ("testing", TestLaunchProcess(kPrintEnvCommand, env_changes, + no_clear_environ, no_clone_flags)); env_changes[kBaseTest] = std::string(); - EXPECT_EQ("\n", - TestLaunchProcess( - echo_base_test, env_changes, no_clear_environ, no_clone_flags)); + EXPECT_EQ("", TestLaunchProcess(kPrintEnvCommand, env_changes, + no_clear_environ, no_clone_flags)); env_changes[kBaseTest] = "foo"; - EXPECT_EQ("foo\n", - TestLaunchProcess( - echo_base_test, env_changes, no_clear_environ, no_clone_flags)); + EXPECT_EQ("foo", TestLaunchProcess(kPrintEnvCommand, env_changes, + no_clear_environ, no_clone_flags)); env_changes.clear(); EXPECT_EQ(0, setenv(kBaseTest, kLargeString, 1 /* override */)); - EXPECT_EQ(std::string(kLargeString) + "\n", - TestLaunchProcess( - echo_base_test, env_changes, no_clear_environ, no_clone_flags)); + EXPECT_EQ(std::string(kLargeString), + TestLaunchProcess(kPrintEnvCommand, env_changes, no_clear_environ, + no_clone_flags)); env_changes[kBaseTest] = "wibble"; - EXPECT_EQ("wibble\n", - TestLaunchProcess( - echo_base_test, env_changes, no_clear_environ, no_clone_flags)); + EXPECT_EQ("wibble", TestLaunchProcess(kPrintEnvCommand, env_changes, + no_clear_environ, no_clone_flags)); #if defined(OS_LINUX) // Test a non-trival value for clone_flags. - EXPECT_EQ("wibble\n", TestLaunchProcess(echo_base_test, env_changes, - no_clear_environ, CLONE_FS)); + EXPECT_EQ("wibble", TestLaunchProcess(kPrintEnvCommand, env_changes, + no_clear_environ, CLONE_FS)); - EXPECT_EQ( - "BASE_TEST=wibble\n", - TestLaunchProcess( - print_env, env_changes, true /* clear_environ */, no_clone_flags)); + EXPECT_EQ("wibble", + TestLaunchProcess(kPrintEnvCommand, env_changes, + true /* clear_environ */, no_clone_flags)); env_changes.clear(); - EXPECT_EQ( - "", - TestLaunchProcess( - print_env, env_changes, true /* clear_environ */, no_clone_flags)); + EXPECT_EQ("", TestLaunchProcess(kPrintEnvCommand, env_changes, + true /* clear_environ */, no_clone_flags)); #endif // defined(OS_LINUX) } -TEST_F(ProcessUtilTest, GetAppOutput) { - std::string output; - -// There's no `true` or `false` on these platforms, so use exit 0/exit 1 -// instead. -#if defined(OS_ANDROID) || defined(OS_FUCHSIA) - std::vector<std::string> argv; -#if defined(OS_FUCHSIA) - // There's no sh in PATH on Fuchsia by default, so provide a full path to sh. - argv.emplace_back("/boot/bin/sh"); -#elif defined(OS_ANDROID) - argv.emplace_back("sh"); // Instead of /bin/sh, force path search to find it. -#else -#error Port. -#endif - argv.emplace_back("-c"); - - argv.emplace_back("exit 0"); - EXPECT_TRUE(GetAppOutput(CommandLine(argv), &output)); - EXPECT_STREQ("", output.c_str()); - - argv[2] = "exit 1"; - EXPECT_FALSE(GetAppOutput(CommandLine(argv), &output)); - EXPECT_STREQ("", output.c_str()); - - argv[2] = "echo foobar42"; - EXPECT_TRUE(GetAppOutput(CommandLine(argv), &output)); - EXPECT_STREQ("foobar42\n", output.c_str()); -#else - EXPECT_TRUE(GetAppOutput(CommandLine(FilePath("true")), &output)); - EXPECT_STREQ("", output.c_str()); - - EXPECT_FALSE(GetAppOutput(CommandLine(FilePath("false")), &output)); - - std::vector<std::string> argv; - argv.emplace_back("/bin/echo"); - argv.emplace_back("-n"); - argv.emplace_back("foobar42"); - EXPECT_TRUE(GetAppOutput(CommandLine(argv), &output)); - EXPECT_STREQ("foobar42", output.c_str()); -#endif // defined(OS_ANDROID) -} - -TEST_F(ProcessUtilTest, GetAppOutputWithExitCode) { - // Test getting output from a successful application. - std::vector<std::string> argv; - std::string output; - int exit_code; - argv.emplace_back(kShellPath); // argv[0] - argv.emplace_back("-c"); // argv[1] - argv.emplace_back("echo foo"); // argv[2]; - EXPECT_TRUE(GetAppOutputWithExitCode(CommandLine(argv), &output, &exit_code)); - EXPECT_STREQ("foo\n", output.c_str()); - EXPECT_EQ(exit_code, kSuccess); - - // Test getting output from an application which fails with a specific exit - // code. - output.clear(); - argv[2] = "echo foo; exit 2"; - EXPECT_TRUE(GetAppOutputWithExitCode(CommandLine(argv), &output, &exit_code)); - EXPECT_STREQ("foo\n", output.c_str()); - EXPECT_EQ(exit_code, 2); -} - // There's no such thing as a parent process id on Fuchsia. #if !defined(OS_FUCHSIA) TEST_F(ProcessUtilTest, GetParentProcessId) { @@ -1138,7 +1072,7 @@ TEST_F(ProcessUtilTest, PreExecHook) { } #endif // !defined(OS_ANDROID) && !defined(OS_FUCHSIA) -#endif // defined(OS_POSIX) +#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID) #if defined(OS_LINUX) MULTIPROCESS_TEST_MAIN(CheckPidProcess) { |