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); |
+ } |
} |
} |