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

Side by Side Diff: services/shell/runner/host/child_process_host.cc

Issue 2419723002: Move services/shell to services/service_manager (Closed)
Patch Set: rebase Created 4 years, 2 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
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "services/shell/runner/host/child_process_host.h"
6
7 #include <stdint.h>
8
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/macros.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/process/kill.h"
18 #include "base/process/launch.h"
19 #include "base/synchronization/lock.h"
20 #include "base/task_runner.h"
21 #include "base/threading/thread_task_runner_handle.h"
22 #include "mojo/edk/embedder/embedder.h"
23 #include "mojo/public/cpp/bindings/interface_ptr_info.h"
24 #include "mojo/public/cpp/system/core.h"
25 #include "services/shell/native_runner_delegate.h"
26 #include "services/shell/runner/common/client_util.h"
27 #include "services/shell/runner/common/switches.h"
28
29 #if defined(OS_LINUX)
30 #include "sandbox/linux/services/namespace_sandbox.h"
31 #endif
32
33 #if defined(OS_WIN)
34 #include "base/win/windows_version.h"
35 #endif
36
37 #if defined(OS_MACOSX)
38 #include "services/shell/runner/host/mach_broker.h"
39 #endif
40
41 namespace shell {
42
43 ChildProcessHost::ChildProcessHost(base::TaskRunner* launch_process_runner,
44 NativeRunnerDelegate* delegate,
45 bool start_sandboxed,
46 const Identity& target,
47 const base::FilePath& app_path)
48 : launch_process_runner_(launch_process_runner),
49 delegate_(delegate),
50 start_sandboxed_(start_sandboxed),
51 target_(target),
52 app_path_(app_path),
53 child_token_(mojo::edk::GenerateRandomToken()),
54 start_child_process_event_(
55 base::WaitableEvent::ResetPolicy::AUTOMATIC,
56 base::WaitableEvent::InitialState::NOT_SIGNALED),
57 weak_factory_(this) {}
58
59 ChildProcessHost::~ChildProcessHost() {
60 if (!app_path_.empty()) {
61 CHECK(!mojo_ipc_channel_)
62 << "Destroying ChildProcessHost before calling Join";
63 }
64 }
65
66 mojom::ServicePtr ChildProcessHost::Start(
67 const Identity& target,
68 const ProcessReadyCallback& callback,
69 const base::Closure& quit_closure) {
70 DCHECK(!child_process_.IsValid());
71
72 const base::CommandLine* parent_command_line =
73 base::CommandLine::ForCurrentProcess();
74 base::FilePath target_path = parent_command_line->GetProgram();
75 // |app_path_| can be empty in tests.
76 if (!app_path_.MatchesExtension(FILE_PATH_LITERAL(".library")) &&
77 !app_path_.empty()) {
78 target_path = app_path_;
79 }
80
81 std::unique_ptr<base::CommandLine> child_command_line(
82 new base::CommandLine(target_path));
83
84 child_command_line->AppendArguments(*parent_command_line, false);
85
86 #ifndef NDEBUG
87 child_command_line->AppendSwitchASCII("n", target.name());
88 child_command_line->AppendSwitchASCII("u", target.user_id());
89 #endif
90
91 if (target_path != app_path_)
92 child_command_line->AppendSwitchPath(switches::kChildProcess, app_path_);
93
94 if (start_sandboxed_)
95 child_command_line->AppendSwitch(switches::kEnableSandbox);
96
97 mojo_ipc_channel_.reset(new mojo::edk::PlatformChannelPair);
98 mojo_ipc_channel_->PrepareToPassClientHandleToChildProcess(
99 child_command_line.get(), &handle_passing_info_);
100
101 mojom::ServicePtr client =
102 PassServiceRequestOnCommandLine(child_command_line.get(),
103 child_token_);
104 launch_process_runner_->PostTaskAndReply(
105 FROM_HERE,
106 base::Bind(&ChildProcessHost::DoLaunch, base::Unretained(this),
107 base::Passed(&child_command_line)),
108 base::Bind(&ChildProcessHost::DidStart,
109 weak_factory_.GetWeakPtr(), callback));
110 return client;
111 }
112
113 void ChildProcessHost::Join() {
114 if (mojo_ipc_channel_)
115 start_child_process_event_.Wait();
116 mojo_ipc_channel_.reset();
117 if (child_process_.IsValid()) {
118 int rv = -1;
119 LOG_IF(ERROR, !child_process_.WaitForExit(&rv))
120 << "Failed to wait for child process";
121 child_process_.Close();
122 }
123 }
124
125 void ChildProcessHost::DidStart(const ProcessReadyCallback& callback) {
126 if (child_process_.IsValid()) {
127 callback.Run(child_process_.Pid());
128 } else {
129 LOG(ERROR) << "Failed to start child process";
130 mojo_ipc_channel_.reset();
131 callback.Run(base::kNullProcessId);
132 }
133 }
134
135 void ChildProcessHost::DoLaunch(
136 std::unique_ptr<base::CommandLine> child_command_line) {
137 if (delegate_) {
138 delegate_->AdjustCommandLineArgumentsForTarget(target_,
139 child_command_line.get());
140 }
141
142 base::LaunchOptions options;
143 #if defined(OS_WIN)
144 options.handles_to_inherit = &handle_passing_info_;
145 #if defined(OFFICIAL_BUILD)
146 CHECK(false) << "Launching mojo process with inherit_handles is insecure!";
147 #endif
148 options.inherit_handles = true;
149 options.stdin_handle = INVALID_HANDLE_VALUE;
150 options.stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
151 options.stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
152 // Always inherit stdout/stderr as a pair.
153 if (!options.stdout_handle || !options.stdin_handle)
154 options.stdin_handle = options.stdout_handle = nullptr;
155
156 // Pseudo handles are used when stdout and stderr redirect to the console. In
157 // that case, they're automatically inherited by child processes. See
158 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682075.aspx
159 // Trying to add them to the list of handles to inherit causes CreateProcess
160 // to fail. When this process is launched from Python then a real handle is
161 // used. In that case, we do want to add it to the list of handles that is
162 // inherited.
163 if (options.stdout_handle &&
164 GetFileType(options.stdout_handle) != FILE_TYPE_CHAR) {
165 handle_passing_info_.push_back(options.stdout_handle);
166 }
167 if (options.stderr_handle &&
168 GetFileType(options.stderr_handle) != FILE_TYPE_CHAR &&
169 options.stdout_handle != options.stderr_handle) {
170 handle_passing_info_.push_back(options.stderr_handle);
171 }
172 #elif defined(OS_POSIX)
173 handle_passing_info_.push_back(std::make_pair(STDIN_FILENO, STDIN_FILENO));
174 handle_passing_info_.push_back(std::make_pair(STDOUT_FILENO, STDOUT_FILENO));
175 handle_passing_info_.push_back(std::make_pair(STDERR_FILENO, STDERR_FILENO));
176 options.fds_to_remap = &handle_passing_info_;
177 #endif
178 DVLOG(2) << "Launching child with command line: "
179 << child_command_line->GetCommandLineString();
180 #if defined(OS_LINUX)
181 if (start_sandboxed_) {
182 child_process_ =
183 sandbox::NamespaceSandbox::LaunchProcess(*child_command_line, options);
184 if (!child_process_.IsValid()) {
185 LOG(ERROR) << "Starting the process with a sandbox failed. Missing kernel"
186 << " support.";
187 }
188 } else
189 #endif
190 {
191 #if defined(OS_MACOSX)
192 MachBroker* mach_broker = MachBroker::GetInstance();
193 base::AutoLock locker(mach_broker->GetLock());
194 #endif
195 child_process_ = base::LaunchProcess(*child_command_line, options);
196 #if defined(OS_MACOSX)
197 mach_broker->ExpectPid(child_process_.Handle());
198 #endif
199 }
200
201 if (child_process_.IsValid()) {
202 DVLOG(0) << "Launched child process pid=" << child_process_.Pid()
203 << ", instance=" << target_.instance()
204 << ", name=" << target_.name()
205 << ", user_id=" << target_.user_id();
206
207 if (mojo_ipc_channel_.get()) {
208 mojo_ipc_channel_->ChildProcessLaunched();
209 mojo::edk::ChildProcessLaunched(
210 child_process_.Handle(),
211 mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle(
212 mojo_ipc_channel_->PassServerHandle().release().handle)),
213 child_token_);
214 }
215 }
216 start_child_process_event_.Signal();
217 }
218
219 } // namespace shell
OLDNEW
« no previous file with comments | « services/shell/runner/host/child_process_host.h ('k') | services/shell/runner/host/child_process_host_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698