Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1990)

Unified Diff: base/process_util_posix.cc

Issue 173261: (Mac) Implement about:memory. (Closed)
Patch Set: Fixed per jrg's (re)review. Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/process_util.h ('k') | base/process_util_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/process_util_posix.cc
diff --git a/base/process_util_posix.cc b/base/process_util_posix.cc
index d365d0131d5b64b12c4b0cdac71fe25e9588f979..18cb255ecfc368397f395eadd5f6251a4321c9c0 100644
--- a/base/process_util_posix.cc
+++ b/base/process_util_posix.cc
@@ -513,10 +513,24 @@ int ProcessMetrics::GetCPUUsage() {
}
#endif
-bool GetAppOutput(const CommandLine& cl, std::string* output) {
+// Executes the application specified by |cl| and wait for it to exit. Stores
+// the output (stdout) in |output|. If |do_search_path| is set, it searches the
+// path for the application; in that case, |envp| must be null, and it will use
+// the current environment. If |do_search_path| is false, |cl| should fully
+// specify the path of the application, and |envp| will be used as the
+// environment. Redirects stderr to /dev/null. Returns true on success
+// (application launched and exited cleanly, with exit code indicating success).
+// |output| is modified only when the function finished successfully.
+static bool GetAppOutputInternal(const CommandLine& cl, char* const envp[],
+ std::string* output, size_t max_output,
+ bool do_search_path) {
int pipe_fd[2];
pid_t pid;
+ // Either |do_search_path| should be false or |envp| should be null, but not
+ // both.
+ DCHECK(!do_search_path ^ !envp);
+
if (pipe(pipe_fd) < 0)
return false;
@@ -555,7 +569,10 @@ bool GetAppOutput(const CommandLine& cl, std::string* output) {
for (size_t i = 0; i < argv.size(); i++)
argv_cstr[i] = const_cast<char*>(argv[i].c_str());
argv_cstr[argv.size()] = NULL;
- execvp(argv_cstr[0], argv_cstr.get());
+ if (do_search_path)
+ execvp(argv_cstr[0], argv_cstr.get());
+ else
+ execve(argv_cstr[0], argv_cstr.get(), envp);
_exit(127);
}
default: // parent
@@ -567,20 +584,28 @@ bool GetAppOutput(const CommandLine& cl, std::string* output) {
char buffer[256];
std::string buf_output;
+ size_t output_left = max_output;
+ ssize_t bytes_read = 1; // A lie to properly handle |max_output == 0|
+ // case in the logic below.
- while (true) {
- ssize_t bytes_read =
- HANDLE_EINTR(read(pipe_fd[0], buffer, sizeof(buffer)));
+ while (output_left > 0) {
+ bytes_read = HANDLE_EINTR(read(pipe_fd[0], buffer,
+ std::min(output_left, sizeof(buffer))));
if (bytes_read <= 0)
break;
buf_output.append(buffer, bytes_read);
+ output_left -= static_cast<size_t>(bytes_read);
}
close(pipe_fd[0]);
- int exit_code = EXIT_FAILURE;
- bool success = WaitForExitCode(pid, &exit_code);
- if (!success || exit_code != EXIT_SUCCESS)
- return false;
+ // If we stopped because we read as much as we wanted, we always declare
+ // success (because the child may exit due to |SIG_PIPE|).
+ if (!(!output_left && bytes_read > 0)) {
+ int exit_code = EXIT_FAILURE;
+ bool success = WaitForExitCode(pid, &exit_code);
+ if (!success || exit_code != EXIT_SUCCESS)
+ return false;
+ }
output->swap(buf_output);
return true;
@@ -588,6 +613,23 @@ bool GetAppOutput(const CommandLine& cl, std::string* output) {
}
}
+bool GetAppOutput(const CommandLine& cl, std::string* output) {
+ // Run |execve()| with the current environment and store "unlimited" data.
+ // (Alas, |SIZE_MAX| is C99 and not everywhere, so we resort to the C++ way of
+ // getting the maximum value for |size_t|.)
+ return GetAppOutputInternal(cl, NULL, output,
+ std::numeric_limits<std::size_t>::max(), true);
+}
+
+// TODO(viettrungluu): Conceivably, we should have a timeout as well, so we
+// don't hang if what we're calling hangs.
+bool GetAppOutputRestricted(const CommandLine& cl,
+ std::string* output, size_t max_output) {
+ // Run |execve()| with the empty environment.
+ char* const empty_environ = NULL;
+ return GetAppOutputInternal(cl, &empty_environ, output, max_output, false);
+}
+
int GetProcessCount(const std::wstring& executable_name,
const ProcessFilter* filter) {
int count = 0;
« no previous file with comments | « base/process_util.h ('k') | base/process_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698