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

Unified Diff: base/process/launch_posix.cc

Issue 2911533002: Use std::vector in process launch code. (Closed)
Patch Set: Created 3 years, 7 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/launch_mac.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/process/launch_posix.cc
diff --git a/base/process/launch_posix.cc b/base/process/launch_posix.cc
index 7550a36f521440e0189603846d5d10f1bd4ed413..b841dee3276eae3cfa9ee7b18c6bf86b14932e3a 100644
--- a/base/process/launch_posix.cc
+++ b/base/process/launch_posix.cc
@@ -317,11 +317,11 @@ Process LaunchProcess(const std::vector<std::string>& argv,
fd_shuffle1.reserve(fd_shuffle_size);
fd_shuffle2.reserve(fd_shuffle_size);
- std::unique_ptr<char* []> argv_cstr(new char*[argv.size() + 1]);
- for (size_t i = 0; i < argv.size(); i++) {
- argv_cstr[i] = const_cast<char*>(argv[i].c_str());
- }
- argv_cstr[argv.size()] = nullptr;
+ std::vector<char*> argv_cstr;
+ argv_cstr.reserve(argv.size() + 1);
+ for (const auto& arg : argv)
+ argv_cstr.push_back(const_cast<char*>(arg.c_str()));
+ argv_cstr.push_back(nullptr);
std::unique_ptr<char* []> new_environ;
char* const empty_environ = nullptr;
@@ -506,7 +506,7 @@ Process LaunchProcess(const std::vector<std::string>& argv,
const char* executable_path = !options.real_path.empty() ?
options.real_path.value().c_str() : argv_cstr[0];
- execvp(executable_path, argv_cstr.get());
+ execvp(executable_path, argv_cstr.data());
RAW_LOG(ERROR, "LaunchProcess: failed to execvp:");
RAW_LOG(ERROR, argv_cstr[0]);
@@ -553,11 +553,12 @@ static bool GetAppOutputInternal(
DCHECK(exit_code);
*exit_code = EXIT_FAILURE;
- int pipe_fd[2];
- pid_t pid;
- InjectiveMultimap fd_shuffle1, fd_shuffle2;
- std::unique_ptr<char* []> argv_cstr(new char*[argv.size() + 1]);
-
+ // Declare and call reserve() here before calling fork() because the child
+ // process cannot allocate memory.
+ std::vector<char*> argv_cstr;
+ argv_cstr.reserve(argv.size() + 1);
+ InjectiveMultimap fd_shuffle1;
+ InjectiveMultimap fd_shuffle2;
fd_shuffle1.reserve(3);
fd_shuffle2.reserve(3);
@@ -565,81 +566,87 @@ static bool GetAppOutputInternal(
// both.
DCHECK(!do_search_path ^ !envp);
+ int pipe_fd[2];
if (pipe(pipe_fd) < 0)
return false;
- switch (pid = fork()) {
- case -1: // error
+ pid_t pid = fork();
+ switch (pid) {
+ case -1: {
+ // error
close(pipe_fd[0]);
close(pipe_fd[1]);
return false;
- case 0: // child
- {
- // DANGER: no calls to malloc or locks are allowed from now on:
- // http://crbug.com/36678
+ }
+ case 0: {
+ // child
+ //
+ // DANGER: no calls to malloc or locks are allowed from now on:
+ // http://crbug.com/36678
#if defined(OS_MACOSX)
- RestoreDefaultExceptionHandler();
+ RestoreDefaultExceptionHandler();
#endif
- // Obscure fork() rule: in the child, if you don't end up doing exec*(),
- // you call _exit() instead of exit(). This is because _exit() does not
- // call any previously-registered (in the parent) exit handlers, which
- // might do things like block waiting for threads that don't even exist
- // in the child.
- int dev_null = open("/dev/null", O_WRONLY);
- if (dev_null < 0)
- _exit(127);
-
- fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true));
- fd_shuffle1.push_back(InjectionArc(
- include_stderr ? pipe_fd[1] : dev_null,
- STDERR_FILENO, true));
- fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true));
- // Adding another element here? Remeber to increase the argument to
- // reserve(), above.
-
- for (size_t i = 0; i < fd_shuffle1.size(); ++i)
- fd_shuffle2.push_back(fd_shuffle1[i]);
-
- if (!ShuffleFileDescriptors(&fd_shuffle1))
- _exit(127);
-
- CloseSuperfluousFds(fd_shuffle2);
-
- for (size_t i = 0; i < argv.size(); i++)
- argv_cstr[i] = const_cast<char*>(argv[i].c_str());
- argv_cstr[argv.size()] = nullptr;
- if (do_search_path)
- execvp(argv_cstr[0], argv_cstr.get());
- else
- execve(argv_cstr[0], argv_cstr.get(), envp);
+ // Obscure fork() rule: in the child, if you don't end up doing exec*(),
+ // you call _exit() instead of exit(). This is because _exit() does not
+ // call any previously-registered (in the parent) exit handlers, which
+ // might do things like block waiting for threads that don't even exist
+ // in the child.
+ int dev_null = open("/dev/null", O_WRONLY);
+ if (dev_null < 0)
_exit(127);
- }
- default: // parent
- {
- // Close our writing end of pipe now. Otherwise later read would not
- // be able to detect end of child's output (in theory we could still
- // write to the pipe).
- close(pipe_fd[1]);
-
- output->clear();
-
- while (true) {
- char buffer[256];
- ssize_t bytes_read =
- HANDLE_EINTR(read(pipe_fd[0], buffer, sizeof(buffer)));
- if (bytes_read <= 0)
- break;
- output->append(buffer, bytes_read);
- }
- close(pipe_fd[0]);
- // Always wait for exit code (even if we know we'll declare
- // GOT_MAX_OUTPUT).
- Process process(pid);
- return process.WaitForExit(exit_code);
+ fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true));
+ fd_shuffle1.push_back(InjectionArc(include_stderr ? pipe_fd[1] : dev_null,
+ STDERR_FILENO, true));
+ fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true));
+ // Adding another element here? Remeber to increase the argument to
+ // reserve(), above.
+
+ for (size_t i = 0; i < fd_shuffle1.size(); ++i)
+ fd_shuffle2.push_back(fd_shuffle1[i]);
+
+ if (!ShuffleFileDescriptors(&fd_shuffle1))
+ _exit(127);
+
+ CloseSuperfluousFds(fd_shuffle2);
+
+ for (const auto& arg : argv)
+ argv_cstr.push_back(const_cast<char*>(arg.c_str()));
+ argv_cstr.push_back(nullptr);
+
+ if (do_search_path)
+ execvp(argv_cstr[0], argv_cstr.data());
+ else
+ execve(argv_cstr[0], argv_cstr.data(), envp);
+ _exit(127);
+ }
+ default: {
+ // parent
+ //
+ // Close our writing end of pipe now. Otherwise later read would not
+ // be able to detect end of child's output (in theory we could still
+ // write to the pipe).
+ close(pipe_fd[1]);
+
+ output->clear();
+
+ while (true) {
+ char buffer[256];
+ ssize_t bytes_read =
+ HANDLE_EINTR(read(pipe_fd[0], buffer, sizeof(buffer)));
+ if (bytes_read <= 0)
+ break;
+ output->append(buffer, bytes_read);
}
+ close(pipe_fd[0]);
+
+ // Always wait for exit code (even if we know we'll declare
+ // GOT_MAX_OUTPUT).
+ Process process(pid);
+ return process.WaitForExit(exit_code);
+ }
}
}
« no previous file with comments | « base/process/launch_mac.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698