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

Side by Side Diff: base/mp/mp_child_process_launcher.cc

Issue 1625015: Refactor ChildProcess and related classes to create a framework outside of br... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 10 years, 8 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/mp/mp_child_process_launcher.h ('k') | base/mp/mp_child_thread.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2009 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 "base/mp/mp_child_process_launcher.h"
6
7 #include "base/command_line.h"
8 #include "base/logging.h"
9 #include "base/scoped_ptr.h"
10 #include "base/thread.h"
11
12 #if defined(OS_POSIX)
13 #include "base/global_descriptors_posix.h"
14 #endif
15
16 namespace base {
17
18 // Having the functionality of MpChildProcessLauncher be in an internal
19 // ref counted object allows us to automatically terminate the process when the
20 // parent class destructs, while still holding on to state that we need.
21 class MpChildProcessLauncher::Context
22 : public base::RefCountedThreadSafe<MpChildProcessLauncher::Context> {
23 public:
24 Context(MpChildProcessContext* process_context)
25 : process_context_(process_context),
26 starting_(true)
27 #if defined(OS_LINUX)
28 , zygote_(false)
29 #endif
30 {
31 }
32
33 void Launch(
34 #if defined(OS_WIN)
35 const FilePath& exposed_dir,
36 #elif defined(OS_POSIX)
37 bool use_zygote,
38 const base::environment_vector& environ,
39 int ipcfd,
40 #endif
41 CommandLine* cmd_line,
42 Client* client) {
43 client_ = client;
44
45 CHECK(process_context_->GetCurrentThreadIdentifier(&client_thread_id_));
46
47 process_context_->PostProcessLauncherTask(
48 FROM_HERE,
49 NewRunnableMethod(
50 this,
51 &Context::LaunchInternal,
52 #if defined(OS_WIN)
53 exposed_dir,
54 #elif defined(POSIX)
55 use_zygote,
56 environ,
57 ipcfd,
58 #endif
59 cmd_line));
60 }
61
62 void ResetClient() {
63 // No need for locking as this function gets called on the same thread that
64 // client_ would be used.
65 CHECK(process_context_->CurrentlyOnThread(client_thread_id_));
66 client_ = NULL;
67 }
68
69 private:
70 friend class base::RefCountedThreadSafe<MpChildProcessLauncher::Context>;
71 friend class MpChildProcessLauncher;
72
73 ~Context() {
74 Terminate();
75 }
76
77 void LaunchInternal(
78 #if defined(OS_WIN)
79 const FilePath& exposed_dir,
80 #elif defined(OS_POSIX)
81 bool use_zygote,
82 const base::environment_vector& env,
83 int ipcfd,
84 #endif
85 CommandLine* cmd_line) {
86 scoped_ptr<CommandLine> cmd_line_deleter(cmd_line);
87 base::ProcessHandle handle = process_context_->StartProcess(
88 #if defined(OS_WIN)
89 exposed_dir,
90 #elif defined(OS_POSIX)
91 use_zygote,
92 cenv,
93 ipcfd,
94 #endif
95 cmd_line);
96
97 process_context_->PostTask(
98 client_thread_id_,
99 FROM_HERE,
100 NewRunnableMethod(
101 this,
102 &MpChildProcessLauncher::Context::Notify,
103 #if defined(OS_LINUX)
104 use_zygote,
105 #endif
106 handle));
107 }
108
109 void Notify(
110 #if defined(OS_LINUX)
111 bool zygote,
112 #endif
113 base::ProcessHandle handle) {
114 starting_ = false;
115 process_.set_handle(handle);
116 #if defined(OS_LINUX)
117 zygote_ = zygote;
118 #endif
119 if (client_) {
120 client_->OnProcessLaunched();
121 } else {
122 Terminate();
123 }
124 }
125
126 void Terminate() {
127 if (!process_.handle())
128 return;
129
130 // On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep! So
131 // don't this on the UI/IO threads.
132 process_context_->PostProcessLauncherTask(
133 FROM_HERE,
134 NewRunnableFunction(
135 &MpChildProcessLauncher::Context::TerminateInternal,
136 #if defined(OS_LINUX)
137 zygote_,
138 #endif
139 process_context_,
140 process_.handle()));
141 process_.set_handle(base::kNullProcessHandle);
142 }
143
144 static void TerminateInternal(
145 #if defined(OS_LINUX)
146 bool zygote,
147 #endif
148 MpChildProcessContext* process_context,
149 base::ProcessHandle handle) {
150 base::Process process(handle);
151 // Client has gone away, so just kill the process. Using exit code 0
152 // means that UMA won't treat this as a crash.
153 process.Terminate(process_context->GetNormalExitResultCode());
154 process_context->EnsureProcessTerminated(handle);
155 process.Close();
156 }
157
158 MpChildProcessContext* process_context_;
159 Client* client_;
160 int client_thread_id_;
161 base::Process process_;
162 bool starting_;
163
164 #if defined(OS_LINUX)
165 bool zygote_;
166 #endif
167 };
168
169
170 MpChildProcessLauncher::MpChildProcessLauncher(
171 #if defined(OS_WIN)
172 const FilePath& exposed_dir,
173 #elif defined(OS_POSIX)
174 bool use_zygote,
175 const base::environment_vector& environ,
176 int ipcfd,
177 #endif
178 CommandLine* cmd_line,
179 MpChildProcessContext* context,
180 Client* client) : process_context_(context) {
181 context_ = new Context(process_context_);
182 context_->Launch(
183 #if defined(OS_WIN)
184 exposed_dir,
185 #elif defined(OS_POSIX)
186 use_zygote,
187 environ,
188 ipcfd,
189 #endif
190 cmd_line,
191 client);
192 }
193
194 MpChildProcessLauncher::~MpChildProcessLauncher() {
195 context_->ResetClient();
196 }
197
198 bool MpChildProcessLauncher::IsStarting() {
199 return context_->starting_;
200 }
201
202 base::ProcessHandle MpChildProcessLauncher::GetHandle() {
203 DCHECK(!context_->starting_);
204 return context_->process_.handle();
205 }
206
207 bool MpChildProcessLauncher::DidProcessCrash() {
208 bool did_crash, child_exited;
209 base::ProcessHandle handle = context_->process_.handle();
210 did_crash = process_context_->CheckProcessCrash(
211 &child_exited,
212 #if defined(OS_POSIX)
213 context_->zygote_,
214 #endif
215 handle);
216
217 // POSIX: If the process crashed, then the kernel closed the socket for it
218 // and so the child has already died by the time we get here. Since
219 // DidProcessCrash called waitpid with WNOHANG, it'll reap the process.
220 // However, if DidProcessCrash didn't reap the child, we'll need to in
221 // Terminate via ProcessWatcher. So we can't close the handle here.
222 if (child_exited)
223 context_->process_.Close();
224
225 return did_crash;
226 }
227
228 void MpChildProcessLauncher::SetProcessBackgrounded(bool background) {
229 DCHECK(!context_->starting_);
230 context_->process_.SetProcessBackgrounded(background);
231 }
232
233 } // namespace base
OLDNEW
« no previous file with comments | « base/mp/mp_child_process_launcher.h ('k') | base/mp/mp_child_thread.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698