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 |