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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « base/process/launch_mac.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/process/launch.h" 5 #include "base/process/launch.h"
6 6
7 #include <dirent.h> 7 #include <dirent.h>
8 #include <errno.h> 8 #include <errno.h>
9 #include <fcntl.h> 9 #include <fcntl.h>
10 #include <sched.h> 10 #include <sched.h>
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 size_t fd_shuffle_size = 0; 310 size_t fd_shuffle_size = 0;
311 if (options.fds_to_remap) { 311 if (options.fds_to_remap) {
312 fd_shuffle_size = options.fds_to_remap->size(); 312 fd_shuffle_size = options.fds_to_remap->size();
313 } 313 }
314 314
315 InjectiveMultimap fd_shuffle1; 315 InjectiveMultimap fd_shuffle1;
316 InjectiveMultimap fd_shuffle2; 316 InjectiveMultimap fd_shuffle2;
317 fd_shuffle1.reserve(fd_shuffle_size); 317 fd_shuffle1.reserve(fd_shuffle_size);
318 fd_shuffle2.reserve(fd_shuffle_size); 318 fd_shuffle2.reserve(fd_shuffle_size);
319 319
320 std::unique_ptr<char* []> argv_cstr(new char*[argv.size() + 1]); 320 std::vector<char*> argv_cstr;
321 for (size_t i = 0; i < argv.size(); i++) { 321 argv_cstr.reserve(argv.size() + 1);
322 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); 322 for (const auto& arg : argv)
323 } 323 argv_cstr.push_back(const_cast<char*>(arg.c_str()));
324 argv_cstr[argv.size()] = nullptr; 324 argv_cstr.push_back(nullptr);
325 325
326 std::unique_ptr<char* []> new_environ; 326 std::unique_ptr<char* []> new_environ;
327 char* const empty_environ = nullptr; 327 char* const empty_environ = nullptr;
328 char* const* old_environ = GetEnvironment(); 328 char* const* old_environ = GetEnvironment();
329 if (options.clear_environ) 329 if (options.clear_environ)
330 old_environ = &empty_environ; 330 old_environ = &empty_environ;
331 if (!options.environ.empty()) 331 if (!options.environ.empty())
332 new_environ = AlterEnvironment(old_environ, options.environ); 332 new_environ = AlterEnvironment(old_environ, options.environ);
333 333
334 sigset_t full_sigset; 334 sigset_t full_sigset;
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 RAW_CHECK(chdir(current_directory) == 0); 499 RAW_CHECK(chdir(current_directory) == 0);
500 } 500 }
501 501
502 if (options.pre_exec_delegate != nullptr) { 502 if (options.pre_exec_delegate != nullptr) {
503 options.pre_exec_delegate->RunAsyncSafe(); 503 options.pre_exec_delegate->RunAsyncSafe();
504 } 504 }
505 505
506 const char* executable_path = !options.real_path.empty() ? 506 const char* executable_path = !options.real_path.empty() ?
507 options.real_path.value().c_str() : argv_cstr[0]; 507 options.real_path.value().c_str() : argv_cstr[0];
508 508
509 execvp(executable_path, argv_cstr.get()); 509 execvp(executable_path, argv_cstr.data());
510 510
511 RAW_LOG(ERROR, "LaunchProcess: failed to execvp:"); 511 RAW_LOG(ERROR, "LaunchProcess: failed to execvp:");
512 RAW_LOG(ERROR, argv_cstr[0]); 512 RAW_LOG(ERROR, argv_cstr[0]);
513 _exit(127); 513 _exit(127);
514 } else { 514 } else {
515 // Parent process 515 // Parent process
516 if (options.wait) { 516 if (options.wait) {
517 // While this isn't strictly disk IO, waiting for another process to 517 // While this isn't strictly disk IO, waiting for another process to
518 // finish is the sort of thing ThreadRestrictions is trying to prevent. 518 // finish is the sort of thing ThreadRestrictions is trying to prevent.
519 base::ThreadRestrictions::AssertIOAllowed(); 519 base::ThreadRestrictions::AssertIOAllowed();
(...skipping 26 matching lines...) Expand all
546 bool include_stderr, 546 bool include_stderr,
547 std::string* output, 547 std::string* output,
548 bool do_search_path, 548 bool do_search_path,
549 int* exit_code) { 549 int* exit_code) {
550 // Doing a blocking wait for another command to finish counts as IO. 550 // Doing a blocking wait for another command to finish counts as IO.
551 base::ThreadRestrictions::AssertIOAllowed(); 551 base::ThreadRestrictions::AssertIOAllowed();
552 // exit_code must be supplied so calling function can determine success. 552 // exit_code must be supplied so calling function can determine success.
553 DCHECK(exit_code); 553 DCHECK(exit_code);
554 *exit_code = EXIT_FAILURE; 554 *exit_code = EXIT_FAILURE;
555 555
556 int pipe_fd[2]; 556 // Declare and call reserve() here before calling fork() because the child
557 pid_t pid; 557 // process cannot allocate memory.
558 InjectiveMultimap fd_shuffle1, fd_shuffle2; 558 std::vector<char*> argv_cstr;
559 std::unique_ptr<char* []> argv_cstr(new char*[argv.size() + 1]); 559 argv_cstr.reserve(argv.size() + 1);
560 560 InjectiveMultimap fd_shuffle1;
561 InjectiveMultimap fd_shuffle2;
561 fd_shuffle1.reserve(3); 562 fd_shuffle1.reserve(3);
562 fd_shuffle2.reserve(3); 563 fd_shuffle2.reserve(3);
563 564
564 // Either |do_search_path| should be false or |envp| should be null, but not 565 // Either |do_search_path| should be false or |envp| should be null, but not
565 // both. 566 // both.
566 DCHECK(!do_search_path ^ !envp); 567 DCHECK(!do_search_path ^ !envp);
567 568
569 int pipe_fd[2];
568 if (pipe(pipe_fd) < 0) 570 if (pipe(pipe_fd) < 0)
569 return false; 571 return false;
570 572
571 switch (pid = fork()) { 573 pid_t pid = fork();
572 case -1: // error 574 switch (pid) {
575 case -1: {
576 // error
573 close(pipe_fd[0]); 577 close(pipe_fd[0]);
574 close(pipe_fd[1]); 578 close(pipe_fd[1]);
575 return false; 579 return false;
576 case 0: // child 580 }
577 { 581 case 0: {
578 // DANGER: no calls to malloc or locks are allowed from now on: 582 // child
579 // http://crbug.com/36678 583 //
584 // DANGER: no calls to malloc or locks are allowed from now on:
585 // http://crbug.com/36678
580 586
581 #if defined(OS_MACOSX) 587 #if defined(OS_MACOSX)
582 RestoreDefaultExceptionHandler(); 588 RestoreDefaultExceptionHandler();
583 #endif 589 #endif
584 590
585 // Obscure fork() rule: in the child, if you don't end up doing exec*(), 591 // Obscure fork() rule: in the child, if you don't end up doing exec*(),
586 // you call _exit() instead of exit(). This is because _exit() does not 592 // you call _exit() instead of exit(). This is because _exit() does not
587 // call any previously-registered (in the parent) exit handlers, which 593 // call any previously-registered (in the parent) exit handlers, which
588 // might do things like block waiting for threads that don't even exist 594 // might do things like block waiting for threads that don't even exist
589 // in the child. 595 // in the child.
590 int dev_null = open("/dev/null", O_WRONLY); 596 int dev_null = open("/dev/null", O_WRONLY);
591 if (dev_null < 0) 597 if (dev_null < 0)
592 _exit(127); 598 _exit(127);
593 599
594 fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true)); 600 fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true));
595 fd_shuffle1.push_back(InjectionArc( 601 fd_shuffle1.push_back(InjectionArc(include_stderr ? pipe_fd[1] : dev_null,
596 include_stderr ? pipe_fd[1] : dev_null, 602 STDERR_FILENO, true));
597 STDERR_FILENO, true)); 603 fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true));
598 fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true)); 604 // Adding another element here? Remeber to increase the argument to
599 // Adding another element here? Remeber to increase the argument to 605 // reserve(), above.
600 // reserve(), above.
601 606
602 for (size_t i = 0; i < fd_shuffle1.size(); ++i) 607 for (size_t i = 0; i < fd_shuffle1.size(); ++i)
603 fd_shuffle2.push_back(fd_shuffle1[i]); 608 fd_shuffle2.push_back(fd_shuffle1[i]);
604 609
605 if (!ShuffleFileDescriptors(&fd_shuffle1)) 610 if (!ShuffleFileDescriptors(&fd_shuffle1))
606 _exit(127); 611 _exit(127);
607 612
608 CloseSuperfluousFds(fd_shuffle2); 613 CloseSuperfluousFds(fd_shuffle2);
609 614
610 for (size_t i = 0; i < argv.size(); i++) 615 for (const auto& arg : argv)
611 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); 616 argv_cstr.push_back(const_cast<char*>(arg.c_str()));
612 argv_cstr[argv.size()] = nullptr; 617 argv_cstr.push_back(nullptr);
613 if (do_search_path) 618
614 execvp(argv_cstr[0], argv_cstr.get()); 619 if (do_search_path)
615 else 620 execvp(argv_cstr[0], argv_cstr.data());
616 execve(argv_cstr[0], argv_cstr.get(), envp); 621 else
617 _exit(127); 622 execve(argv_cstr[0], argv_cstr.data(), envp);
623 _exit(127);
624 }
625 default: {
626 // parent
627 //
628 // Close our writing end of pipe now. Otherwise later read would not
629 // be able to detect end of child's output (in theory we could still
630 // write to the pipe).
631 close(pipe_fd[1]);
632
633 output->clear();
634
635 while (true) {
636 char buffer[256];
637 ssize_t bytes_read =
638 HANDLE_EINTR(read(pipe_fd[0], buffer, sizeof(buffer)));
639 if (bytes_read <= 0)
640 break;
641 output->append(buffer, bytes_read);
618 } 642 }
619 default: // parent 643 close(pipe_fd[0]);
620 {
621 // Close our writing end of pipe now. Otherwise later read would not
622 // be able to detect end of child's output (in theory we could still
623 // write to the pipe).
624 close(pipe_fd[1]);
625 644
626 output->clear(); 645 // Always wait for exit code (even if we know we'll declare
627 646 // GOT_MAX_OUTPUT).
628 while (true) { 647 Process process(pid);
629 char buffer[256]; 648 return process.WaitForExit(exit_code);
630 ssize_t bytes_read = 649 }
631 HANDLE_EINTR(read(pipe_fd[0], buffer, sizeof(buffer)));
632 if (bytes_read <= 0)
633 break;
634 output->append(buffer, bytes_read);
635 }
636 close(pipe_fd[0]);
637
638 // Always wait for exit code (even if we know we'll declare
639 // GOT_MAX_OUTPUT).
640 Process process(pid);
641 return process.WaitForExit(exit_code);
642 }
643 } 650 }
644 } 651 }
645 652
646 bool GetAppOutput(const CommandLine& cl, std::string* output) { 653 bool GetAppOutput(const CommandLine& cl, std::string* output) {
647 return GetAppOutput(cl.argv(), output); 654 return GetAppOutput(cl.argv(), output);
648 } 655 }
649 656
650 bool GetAppOutput(const std::vector<std::string>& argv, std::string* output) { 657 bool GetAppOutput(const std::vector<std::string>& argv, std::string* output) {
651 // Run |execve()| with the current environment. 658 // Run |execve()| with the current environment.
652 int exit_code; 659 int exit_code;
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
766 jmp_buf env; 773 jmp_buf env;
767 if (setjmp(env) == 0) { 774 if (setjmp(env) == 0) {
768 return CloneAndLongjmpInChild(flags, ptid, ctid, &env); 775 return CloneAndLongjmpInChild(flags, ptid, ctid, &env);
769 } 776 }
770 777
771 return 0; 778 return 0;
772 } 779 }
773 #endif // defined(OS_LINUX) || defined(OS_NACL_NONSFI) 780 #endif // defined(OS_LINUX) || defined(OS_NACL_NONSFI)
774 781
775 } // namespace base 782 } // namespace base
OLDNEW
« 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