| 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 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 *scratch++ = '='; | 495 *scratch++ = '='; |
| 496 memcpy(scratch, j->second.c_str(), j->second.size() + 1); | 496 memcpy(scratch, j->second.c_str(), j->second.size() + 1); |
| 497 scratch += j->second.size() + 1; | 497 scratch += j->second.size() + 1; |
| 498 } | 498 } |
| 499 } | 499 } |
| 500 | 500 |
| 501 ret[k] = NULL; | 501 ret[k] = NULL; |
| 502 return ret; | 502 return ret; |
| 503 } | 503 } |
| 504 | 504 |
| 505 bool LaunchAppImpl( | 505 bool LaunchProcess(const std::vector<std::string>& argv, |
| 506 const std::vector<std::string>& argv, | 506 const LaunchOptions& options) { |
| 507 const environment_vector& env_changes, | |
| 508 const file_handle_mapping_vector& fds_to_remap, | |
| 509 bool wait, | |
| 510 ProcessHandle* process_handle, | |
| 511 bool start_new_process_group) { | |
| 512 pid_t pid; | 507 pid_t pid; |
| 513 InjectiveMultimap fd_shuffle1, fd_shuffle2; | 508 InjectiveMultimap fd_shuffle1, fd_shuffle2; |
| 514 fd_shuffle1.reserve(fds_to_remap.size()); | 509 if (options.fds_to_remap) { |
| 515 fd_shuffle2.reserve(fds_to_remap.size()); | 510 fd_shuffle1.reserve(options.fds_to_remap->size()); |
| 511 fd_shuffle2.reserve(options.fds_to_remap->size()); |
| 512 } |
| 516 scoped_array<char*> argv_cstr(new char*[argv.size() + 1]); | 513 scoped_array<char*> argv_cstr(new char*[argv.size() + 1]); |
| 517 scoped_array<char*> new_environ(AlterEnvironment(env_changes, environ)); | 514 scoped_array<char*> new_environ; |
| 515 if (options.environ) |
| 516 new_environ.reset(AlterEnvironment(*options.environ, environ)); |
| 518 | 517 |
| 519 pid = fork(); | 518 pid = fork(); |
| 520 if (pid < 0) { | 519 if (pid < 0) { |
| 521 PLOG(ERROR) << "fork"; | 520 PLOG(ERROR) << "fork"; |
| 522 return false; | 521 return false; |
| 523 } | 522 } |
| 524 if (pid == 0) { | 523 if (pid == 0) { |
| 525 // Child process | 524 // Child process |
| 526 | 525 |
| 527 // DANGER: fork() rule: in the child, if you don't end up doing exec*(), | 526 // DANGER: fork() rule: in the child, if you don't end up doing exec*(), |
| (...skipping 11 matching lines...) Expand all Loading... |
| 539 _exit(127); | 538 _exit(127); |
| 540 } | 539 } |
| 541 | 540 |
| 542 file_util::ScopedFD null_fd_closer(&null_fd); | 541 file_util::ScopedFD null_fd_closer(&null_fd); |
| 543 int new_fd = HANDLE_EINTR(dup2(null_fd, STDIN_FILENO)); | 542 int new_fd = HANDLE_EINTR(dup2(null_fd, STDIN_FILENO)); |
| 544 if (new_fd != STDIN_FILENO) { | 543 if (new_fd != STDIN_FILENO) { |
| 545 RAW_LOG(ERROR, "Failed to dup /dev/null for stdin"); | 544 RAW_LOG(ERROR, "Failed to dup /dev/null for stdin"); |
| 546 _exit(127); | 545 _exit(127); |
| 547 } | 546 } |
| 548 | 547 |
| 549 if (start_new_process_group) { | 548 if (options.new_process_group) { |
| 550 // Instead of inheriting the process group ID of the parent, the child | 549 // Instead of inheriting the process group ID of the parent, the child |
| 551 // starts off a new process group with pgid equal to its process ID. | 550 // starts off a new process group with pgid equal to its process ID. |
| 552 if (setpgid(0, 0) < 0) { | 551 if (setpgid(0, 0) < 0) { |
| 553 RAW_LOG(ERROR, "setpgid failed"); | 552 RAW_LOG(ERROR, "setpgid failed"); |
| 554 _exit(127); | 553 _exit(127); |
| 555 } | 554 } |
| 556 } | 555 } |
| 557 #if defined(OS_MACOSX) | 556 #if defined(OS_MACOSX) |
| 558 RestoreDefaultExceptionHandler(); | 557 RestoreDefaultExceptionHandler(); |
| 559 #endif | 558 #endif |
| 560 | 559 |
| 561 ResetChildSignalHandlersToDefaults(); | 560 ResetChildSignalHandlersToDefaults(); |
| 562 | 561 |
| 563 #if 0 | 562 #if 0 |
| 564 // When debugging it can be helpful to check that we really aren't making | 563 // When debugging it can be helpful to check that we really aren't making |
| 565 // any hidden calls to malloc. | 564 // any hidden calls to malloc. |
| 566 void *malloc_thunk = | 565 void *malloc_thunk = |
| 567 reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095); | 566 reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095); |
| 568 mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC); | 567 mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC); |
| 569 memset(reinterpret_cast<void*>(malloc), 0xff, 8); | 568 memset(reinterpret_cast<void*>(malloc), 0xff, 8); |
| 570 #endif | 569 #endif |
| 571 | 570 |
| 572 // DANGER: no calls to malloc are allowed from now on: | 571 // DANGER: no calls to malloc are allowed from now on: |
| 573 // http://crbug.com/36678 | 572 // http://crbug.com/36678 |
| 574 | 573 |
| 575 for (file_handle_mapping_vector::const_iterator | 574 if (options.fds_to_remap) { |
| 576 it = fds_to_remap.begin(); it != fds_to_remap.end(); ++it) { | 575 for (file_handle_mapping_vector::const_iterator |
| 577 fd_shuffle1.push_back(InjectionArc(it->first, it->second, false)); | 576 it = options.fds_to_remap->begin(); |
| 578 fd_shuffle2.push_back(InjectionArc(it->first, it->second, false)); | 577 it != options.fds_to_remap->end(); ++it) { |
| 578 fd_shuffle1.push_back(InjectionArc(it->first, it->second, false)); |
| 579 fd_shuffle2.push_back(InjectionArc(it->first, it->second, false)); |
| 580 } |
| 579 } | 581 } |
| 580 | 582 |
| 581 environ = new_environ.get(); | 583 if (options.environ) |
| 584 environ = new_environ.get(); |
| 582 | 585 |
| 583 // fd_shuffle1 is mutated by this call because it cannot malloc. | 586 // fd_shuffle1 is mutated by this call because it cannot malloc. |
| 584 if (!ShuffleFileDescriptors(&fd_shuffle1)) | 587 if (!ShuffleFileDescriptors(&fd_shuffle1)) |
| 585 _exit(127); | 588 _exit(127); |
| 586 | 589 |
| 587 CloseSuperfluousFds(fd_shuffle2); | 590 CloseSuperfluousFds(fd_shuffle2); |
| 588 | 591 |
| 589 for (size_t i = 0; i < argv.size(); i++) | 592 for (size_t i = 0; i < argv.size(); i++) |
| 590 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); | 593 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); |
| 591 argv_cstr[argv.size()] = NULL; | 594 argv_cstr[argv.size()] = NULL; |
| 592 execvp(argv_cstr[0], argv_cstr.get()); | 595 execvp(argv_cstr[0], argv_cstr.get()); |
| 593 RAW_LOG(ERROR, "LaunchApp: failed to execvp:"); | 596 RAW_LOG(ERROR, "LaunchApp: failed to execvp:"); |
| 594 RAW_LOG(ERROR, argv_cstr[0]); | 597 RAW_LOG(ERROR, argv_cstr[0]); |
| 595 _exit(127); | 598 _exit(127); |
| 596 } else { | 599 } else { |
| 597 // Parent process | 600 // Parent process |
| 598 if (wait) { | 601 if (options.wait) { |
| 599 // While this isn't strictly disk IO, waiting for another process to | 602 // While this isn't strictly disk IO, waiting for another process to |
| 600 // finish is the sort of thing ThreadRestrictions is trying to prevent. | 603 // finish is the sort of thing ThreadRestrictions is trying to prevent. |
| 601 base::ThreadRestrictions::AssertIOAllowed(); | 604 base::ThreadRestrictions::AssertIOAllowed(); |
| 602 pid_t ret = HANDLE_EINTR(waitpid(pid, 0, 0)); | 605 pid_t ret = HANDLE_EINTR(waitpid(pid, 0, 0)); |
| 603 DPCHECK(ret > 0); | 606 DPCHECK(ret > 0); |
| 604 } | 607 } |
| 605 | 608 |
| 606 if (process_handle) | 609 if (options.process_handle) |
| 607 *process_handle = pid; | 610 *options.process_handle = pid; |
| 608 } | 611 } |
| 609 | 612 |
| 610 return true; | 613 return true; |
| 611 } | 614 } |
| 612 | 615 |
| 613 bool LaunchApp( | 616 bool LaunchProcess(const CommandLine& cmdline, |
| 614 const std::vector<std::string>& argv, | 617 const LaunchOptions& options) { |
| 615 const environment_vector& env_changes, | 618 return LaunchProcess(cl.argv(), options); |
| 616 const file_handle_mapping_vector& fds_to_remap, | |
| 617 bool wait, | |
| 618 ProcessHandle* process_handle) { | |
| 619 return LaunchAppImpl(argv, env_changes, fds_to_remap, | |
| 620 wait, process_handle, false); | |
| 621 } | |
| 622 | |
| 623 bool LaunchAppInNewProcessGroup( | |
| 624 const std::vector<std::string>& argv, | |
| 625 const environment_vector& env_changes, | |
| 626 const file_handle_mapping_vector& fds_to_remap, | |
| 627 bool wait, | |
| 628 ProcessHandle* process_handle) { | |
| 629 return LaunchAppImpl(argv, env_changes, fds_to_remap, wait, | |
| 630 process_handle, true); | |
| 631 } | |
| 632 | |
| 633 bool LaunchApp(const std::vector<std::string>& argv, | |
| 634 const file_handle_mapping_vector& fds_to_remap, | |
| 635 bool wait, ProcessHandle* process_handle) { | |
| 636 base::environment_vector no_env; | |
| 637 return LaunchApp(argv, no_env, fds_to_remap, wait, process_handle); | |
| 638 } | |
| 639 | |
| 640 bool LaunchApp(const CommandLine& cl, | |
| 641 bool wait, bool start_hidden, | |
| 642 ProcessHandle* process_handle) { | |
| 643 file_handle_mapping_vector no_files; | |
| 644 return LaunchApp(cl.argv(), no_files, wait, process_handle); | |
| 645 } | 619 } |
| 646 | 620 |
| 647 ProcessMetrics::~ProcessMetrics() { } | 621 ProcessMetrics::~ProcessMetrics() { } |
| 648 | 622 |
| 649 void EnableTerminationOnHeapCorruption() { | 623 void EnableTerminationOnHeapCorruption() { |
| 650 // On POSIX, there nothing to do AFAIK. | 624 // On POSIX, there nothing to do AFAIK. |
| 651 } | 625 } |
| 652 | 626 |
| 653 bool EnableInProcessStackDumping() { | 627 bool EnableInProcessStackDumping() { |
| 654 // When running in an application, our code typically expects SIGPIPE | 628 // When running in an application, our code typically expects SIGPIPE |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 const ProcessFilter* filter) { | 979 const ProcessFilter* filter) { |
| 1006 bool exited_cleanly = | 980 bool exited_cleanly = |
| 1007 WaitForProcessesToExit(executable_name, wait_milliseconds, | 981 WaitForProcessesToExit(executable_name, wait_milliseconds, |
| 1008 filter); | 982 filter); |
| 1009 if (!exited_cleanly) | 983 if (!exited_cleanly) |
| 1010 KillProcesses(executable_name, exit_code, filter); | 984 KillProcesses(executable_name, exit_code, filter); |
| 1011 return exited_cleanly; | 985 return exited_cleanly; |
| 1012 } | 986 } |
| 1013 | 987 |
| 1014 } // namespace base | 988 } // namespace base |
| OLD | NEW |