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

Side by Side Diff: base/process_util_posix.cc

Issue 7283019: base: refactor LaunchApp variants into a single function (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 9 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « base/process_util.h ('k') | base/process_util_win.cc » ('j') | 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) 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
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
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
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
OLDNEW
« no previous file with comments | « base/process_util.h ('k') | base/process_util_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698