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 |