| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <dirent.h> | 5 #include <dirent.h> |
| 6 #include <errno.h> | 6 #include <errno.h> |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <signal.h> | 8 #include <signal.h> |
| 9 #include <stdlib.h> | 9 #include <stdlib.h> |
| 10 #include <sys/resource.h> | 10 #include <sys/resource.h> |
| (...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 520 *scratch++ = '='; | 520 *scratch++ = '='; |
| 521 memcpy(scratch, j->second.c_str(), j->second.size() + 1); | 521 memcpy(scratch, j->second.c_str(), j->second.size() + 1); |
| 522 scratch += j->second.size() + 1; | 522 scratch += j->second.size() + 1; |
| 523 } | 523 } |
| 524 } | 524 } |
| 525 | 525 |
| 526 ret[k] = NULL; | 526 ret[k] = NULL; |
| 527 return ret; | 527 return ret; |
| 528 } | 528 } |
| 529 | 529 |
| 530 bool LaunchAppImpl( | 530 bool LaunchProcess(const std::vector<std::string>& argv, |
| 531 const std::vector<std::string>& argv, | 531 const LaunchOptions& options) { |
| 532 const environment_vector& env_changes, | |
| 533 const file_handle_mapping_vector& fds_to_remap, | |
| 534 bool wait, | |
| 535 ProcessHandle* process_handle, | |
| 536 bool start_new_process_group) { | |
| 537 pid_t pid; | 532 pid_t pid; |
| 538 InjectiveMultimap fd_shuffle1, fd_shuffle2; | 533 InjectiveMultimap fd_shuffle1, fd_shuffle2; |
| 539 fd_shuffle1.reserve(fds_to_remap.size()); | 534 if (options.fds_to_remap) { |
| 540 fd_shuffle2.reserve(fds_to_remap.size()); | 535 fd_shuffle1.reserve(options.fds_to_remap->size()); |
| 536 fd_shuffle2.reserve(options.fds_to_remap->size()); |
| 537 } |
| 541 scoped_array<char*> argv_cstr(new char*[argv.size() + 1]); | 538 scoped_array<char*> argv_cstr(new char*[argv.size() + 1]); |
| 542 scoped_array<char*> new_environ(AlterEnvironment(env_changes, | 539 scoped_array<char*> new_environ; |
| 543 GetEnvironment())); | 540 if (options.environ) |
| 541 new_environ.reset(AlterEnvironment(*options.environ, GetEnvironment())); |
| 544 | 542 |
| 545 pid = fork(); | 543 pid = fork(); |
| 546 if (pid < 0) { | 544 if (pid < 0) { |
| 547 PLOG(ERROR) << "fork"; | 545 PLOG(ERROR) << "fork"; |
| 548 return false; | 546 return false; |
| 549 } | 547 } |
| 550 if (pid == 0) { | 548 if (pid == 0) { |
| 551 // Child process | 549 // Child process |
| 552 | 550 |
| 553 // DANGER: fork() rule: in the child, if you don't end up doing exec*(), | 551 // DANGER: fork() rule: in the child, if you don't end up doing exec*(), |
| (...skipping 11 matching lines...) Expand all Loading... |
| 565 _exit(127); | 563 _exit(127); |
| 566 } | 564 } |
| 567 | 565 |
| 568 file_util::ScopedFD null_fd_closer(&null_fd); | 566 file_util::ScopedFD null_fd_closer(&null_fd); |
| 569 int new_fd = HANDLE_EINTR(dup2(null_fd, STDIN_FILENO)); | 567 int new_fd = HANDLE_EINTR(dup2(null_fd, STDIN_FILENO)); |
| 570 if (new_fd != STDIN_FILENO) { | 568 if (new_fd != STDIN_FILENO) { |
| 571 RAW_LOG(ERROR, "Failed to dup /dev/null for stdin"); | 569 RAW_LOG(ERROR, "Failed to dup /dev/null for stdin"); |
| 572 _exit(127); | 570 _exit(127); |
| 573 } | 571 } |
| 574 | 572 |
| 575 if (start_new_process_group) { | 573 if (options.new_process_group) { |
| 576 // Instead of inheriting the process group ID of the parent, the child | 574 // Instead of inheriting the process group ID of the parent, the child |
| 577 // starts off a new process group with pgid equal to its process ID. | 575 // starts off a new process group with pgid equal to its process ID. |
| 578 if (setpgid(0, 0) < 0) { | 576 if (setpgid(0, 0) < 0) { |
| 579 RAW_LOG(ERROR, "setpgid failed"); | 577 RAW_LOG(ERROR, "setpgid failed"); |
| 580 _exit(127); | 578 _exit(127); |
| 581 } | 579 } |
| 582 } | 580 } |
| 583 #if defined(OS_MACOSX) | 581 #if defined(OS_MACOSX) |
| 584 RestoreDefaultExceptionHandler(); | 582 RestoreDefaultExceptionHandler(); |
| 585 #endif | 583 #endif |
| 586 | 584 |
| 587 ResetChildSignalHandlersToDefaults(); | 585 ResetChildSignalHandlersToDefaults(); |
| 588 | 586 |
| 589 #if 0 | 587 #if 0 |
| 590 // When debugging it can be helpful to check that we really aren't making | 588 // When debugging it can be helpful to check that we really aren't making |
| 591 // any hidden calls to malloc. | 589 // any hidden calls to malloc. |
| 592 void *malloc_thunk = | 590 void *malloc_thunk = |
| 593 reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095); | 591 reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095); |
| 594 mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC); | 592 mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC); |
| 595 memset(reinterpret_cast<void*>(malloc), 0xff, 8); | 593 memset(reinterpret_cast<void*>(malloc), 0xff, 8); |
| 596 #endif | 594 #endif |
| 597 | 595 |
| 598 // DANGER: no calls to malloc are allowed from now on: | 596 // DANGER: no calls to malloc are allowed from now on: |
| 599 // http://crbug.com/36678 | 597 // http://crbug.com/36678 |
| 600 | 598 |
| 601 for (file_handle_mapping_vector::const_iterator | 599 if (options.fds_to_remap) { |
| 602 it = fds_to_remap.begin(); it != fds_to_remap.end(); ++it) { | 600 for (file_handle_mapping_vector::const_iterator |
| 603 fd_shuffle1.push_back(InjectionArc(it->first, it->second, false)); | 601 it = options.fds_to_remap->begin(); |
| 604 fd_shuffle2.push_back(InjectionArc(it->first, it->second, false)); | 602 it != options.fds_to_remap->end(); ++it) { |
| 603 fd_shuffle1.push_back(InjectionArc(it->first, it->second, false)); |
| 604 fd_shuffle2.push_back(InjectionArc(it->first, it->second, false)); |
| 605 } |
| 605 } | 606 } |
| 606 | 607 |
| 607 SetEnvironment(new_environ.get()); | 608 if (options.environ) |
| 609 SetEnvironment(new_environ.get()); |
| 608 | 610 |
| 609 // fd_shuffle1 is mutated by this call because it cannot malloc. | 611 // fd_shuffle1 is mutated by this call because it cannot malloc. |
| 610 if (!ShuffleFileDescriptors(&fd_shuffle1)) | 612 if (!ShuffleFileDescriptors(&fd_shuffle1)) |
| 611 _exit(127); | 613 _exit(127); |
| 612 | 614 |
| 613 CloseSuperfluousFds(fd_shuffle2); | 615 CloseSuperfluousFds(fd_shuffle2); |
| 614 | 616 |
| 615 for (size_t i = 0; i < argv.size(); i++) | 617 for (size_t i = 0; i < argv.size(); i++) |
| 616 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); | 618 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); |
| 617 argv_cstr[argv.size()] = NULL; | 619 argv_cstr[argv.size()] = NULL; |
| 618 execvp(argv_cstr[0], argv_cstr.get()); | 620 execvp(argv_cstr[0], argv_cstr.get()); |
| 619 RAW_LOG(ERROR, "LaunchApp: failed to execvp:"); | 621 RAW_LOG(ERROR, "LaunchApp: failed to execvp:"); |
| 620 RAW_LOG(ERROR, argv_cstr[0]); | 622 RAW_LOG(ERROR, argv_cstr[0]); |
| 621 _exit(127); | 623 _exit(127); |
| 622 } else { | 624 } else { |
| 623 // Parent process | 625 // Parent process |
| 624 if (wait) { | 626 if (options.wait) { |
| 625 // While this isn't strictly disk IO, waiting for another process to | 627 // While this isn't strictly disk IO, waiting for another process to |
| 626 // finish is the sort of thing ThreadRestrictions is trying to prevent. | 628 // finish is the sort of thing ThreadRestrictions is trying to prevent. |
| 627 base::ThreadRestrictions::AssertIOAllowed(); | 629 base::ThreadRestrictions::AssertIOAllowed(); |
| 628 pid_t ret = HANDLE_EINTR(waitpid(pid, 0, 0)); | 630 pid_t ret = HANDLE_EINTR(waitpid(pid, 0, 0)); |
| 629 DPCHECK(ret > 0); | 631 DPCHECK(ret > 0); |
| 630 } | 632 } |
| 631 | 633 |
| 632 if (process_handle) | 634 if (options.process_handle) |
| 633 *process_handle = pid; | 635 *options.process_handle = pid; |
| 634 } | 636 } |
| 635 | 637 |
| 636 return true; | 638 return true; |
| 637 } | 639 } |
| 638 | 640 |
| 639 bool LaunchApp( | 641 bool LaunchProcess(const CommandLine& cmdline, |
| 640 const std::vector<std::string>& argv, | 642 const LaunchOptions& options) { |
| 641 const environment_vector& env_changes, | 643 return LaunchProcess(cmdline.argv(), options); |
| 642 const file_handle_mapping_vector& fds_to_remap, | |
| 643 bool wait, | |
| 644 ProcessHandle* process_handle) { | |
| 645 return LaunchAppImpl(argv, env_changes, fds_to_remap, | |
| 646 wait, process_handle, false); | |
| 647 } | |
| 648 | |
| 649 bool LaunchAppInNewProcessGroup( | |
| 650 const std::vector<std::string>& argv, | |
| 651 const environment_vector& env_changes, | |
| 652 const file_handle_mapping_vector& fds_to_remap, | |
| 653 bool wait, | |
| 654 ProcessHandle* process_handle) { | |
| 655 return LaunchAppImpl(argv, env_changes, fds_to_remap, wait, | |
| 656 process_handle, true); | |
| 657 } | |
| 658 | |
| 659 bool LaunchApp(const std::vector<std::string>& argv, | |
| 660 const file_handle_mapping_vector& fds_to_remap, | |
| 661 bool wait, ProcessHandle* process_handle) { | |
| 662 base::environment_vector no_env; | |
| 663 return LaunchApp(argv, no_env, fds_to_remap, wait, process_handle); | |
| 664 } | |
| 665 | |
| 666 bool LaunchApp(const CommandLine& cl, | |
| 667 bool wait, bool start_hidden, | |
| 668 ProcessHandle* process_handle) { | |
| 669 file_handle_mapping_vector no_files; | |
| 670 return LaunchApp(cl.argv(), no_files, wait, process_handle); | |
| 671 } | 644 } |
| 672 | 645 |
| 673 ProcessMetrics::~ProcessMetrics() { } | 646 ProcessMetrics::~ProcessMetrics() { } |
| 674 | 647 |
| 675 void EnableTerminationOnHeapCorruption() { | 648 void EnableTerminationOnHeapCorruption() { |
| 676 // On POSIX, there nothing to do AFAIK. | 649 // On POSIX, there nothing to do AFAIK. |
| 677 } | 650 } |
| 678 | 651 |
| 679 bool EnableInProcessStackDumping() { | 652 bool EnableInProcessStackDumping() { |
| 680 // When running in an application, our code typically expects SIGPIPE | 653 // When running in an application, our code typically expects SIGPIPE |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1034 const ProcessFilter* filter) { | 1007 const ProcessFilter* filter) { |
| 1035 bool exited_cleanly = | 1008 bool exited_cleanly = |
| 1036 WaitForProcessesToExit(executable_name, wait_milliseconds, | 1009 WaitForProcessesToExit(executable_name, wait_milliseconds, |
| 1037 filter); | 1010 filter); |
| 1038 if (!exited_cleanly) | 1011 if (!exited_cleanly) |
| 1039 KillProcesses(executable_name, exit_code, filter); | 1012 KillProcesses(executable_name, exit_code, filter); |
| 1040 return exited_cleanly; | 1013 return exited_cleanly; |
| 1041 } | 1014 } |
| 1042 | 1015 |
| 1043 } // namespace base | 1016 } // namespace base |
| OLD | NEW |