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

Side by Side Diff: ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc

Issue 10830149: Kill pnacl translation processes immediately on coordinator error and destruction (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "native_client/src/trusted/plugin/pnacl_translate_thread.h" 5 #include "native_client/src/trusted/plugin/pnacl_translate_thread.h"
6 6
7 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" 7 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
8 #include "native_client/src/trusted/plugin/plugin.h" 8 #include "native_client/src/trusted/plugin/plugin.h"
9 #include "native_client/src/trusted/plugin/pnacl_resources.h" 9 #include "native_client/src/trusted/plugin/pnacl_resources.h"
10 #include "native_client/src/trusted/plugin/srpc_params.h" 10 #include "native_client/src/trusted/plugin/srpc_params.h"
11 #include "native_client/src/trusted/plugin/temporary_file.h" 11 #include "native_client/src/trusted/plugin/temporary_file.h"
12 #include "native_client/src/trusted/plugin/utility.h" 12 #include "native_client/src/trusted/plugin/utility.h"
13 13
14 namespace plugin { 14 namespace plugin {
15 15
16 PnaclTranslateThread::PnaclTranslateThread() : subprocesses_should_die_(false), 16 PnaclTranslateThread::PnaclTranslateThread() : done_(false),
17 current_rev_interface_(NULL),
18 done_(false),
19 manifest_(NULL), 17 manifest_(NULL),
20 ld_manifest_(NULL), 18 ld_manifest_(NULL),
21 obj_file_(NULL), 19 obj_file_(NULL),
22 nexe_file_(NULL), 20 nexe_file_(NULL),
23 coordinator_error_info_(NULL), 21 coordinator_error_info_(NULL),
24 resources_(NULL), 22 resources_(NULL),
25 plugin_(NULL) { 23 plugin_(NULL) {
26 NaClXMutexCtor(&subprocess_mu_); 24 NaClXMutexCtor(&subprocess_mu_);
27 NaClXMutexCtor(&cond_mu_); 25 NaClXMutexCtor(&cond_mu_);
28 NaClXCondVarCtor(&buffer_cond_); 26 NaClXCondVarCtor(&buffer_cond_);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 } 113 }
116 114
117 void WINAPI PnaclTranslateThread::DoTranslateThread(void* arg) { 115 void WINAPI PnaclTranslateThread::DoTranslateThread(void* arg) {
118 PnaclTranslateThread* translator = 116 PnaclTranslateThread* translator =
119 reinterpret_cast<PnaclTranslateThread*>(arg); 117 reinterpret_cast<PnaclTranslateThread*>(arg);
120 translator->DoTranslate(); 118 translator->DoTranslate();
121 } 119 }
122 120
123 void PnaclTranslateThread::DoTranslate() { 121 void PnaclTranslateThread::DoTranslate() {
124 ErrorInfo error_info; 122 ErrorInfo error_info;
125 nacl::scoped_ptr<NaClSubprocess> llc_subprocess(
126 StartSubprocess(PnaclUrls::GetLlcUrl(), manifest_, &error_info));
127 if (llc_subprocess == NULL) {
128 TranslateFailed("Compile process could not be created: " +
129 error_info.message());
130 return;
131 }
132 // Run LLC.
133 SrpcParams params; 123 SrpcParams params;
134 nacl::DescWrapper* llc_out_file = obj_file_->get_wrapper(); 124 nacl::DescWrapper* llc_out_file = obj_file_->get_wrapper();
135 PluginReverseInterface* llc_reverse =
136 llc_subprocess->service_runtime()->rev_interface();
137 llc_reverse->AddTempQuotaManagedFile(obj_file_->identifier());
138 RegisterReverseInterface(llc_reverse);
139 125
140 if (!llc_subprocess->InvokeSrpcMethod("StreamInit", 126 {
141 "h", 127 nacl::MutexLocker ml(&subprocess_mu_);
142 &params, 128 llc_subprocess_.reset(
143 llc_out_file->desc())) { 129 StartSubprocess(PnaclUrls::GetLlcUrl(), manifest_, &error_info));
144 // StreamInit returns an error message if the RPC fails. 130 if (llc_subprocess_ == NULL) {
145 TranslateFailed(nacl::string("Stream init failed: ") + 131 TranslateFailed("Compile process could not be created: " +
146 nacl::string(params.outs()[0]->arrays.str)); 132 error_info.message());
133 return;
134 }
135 // Run LLC.
136 PluginReverseInterface* llc_reverse =
137 llc_subprocess_->service_runtime()->rev_interface();
138 llc_reverse->AddTempQuotaManagedFile(obj_file_->identifier());
139 }
140
141 if (!llc_subprocess_->InvokeSrpcMethod("StreamInit",
142 "h",
143 &params,
144 llc_out_file->desc())) {
145 if (llc_subprocess_->srpc_client()->GetLastError() ==
146 NACL_SRPC_RESULT_APP_ERROR) {
147 // The error message is only present if the error was returned from llc
148 TranslateFailed(nacl::string("Stream init failed: ") +
149 nacl::string(params.outs()[0]->arrays.str));
150 } else {
151 TranslateFailed("Stream init internal error");
152 }
147 return; 153 return;
148 } 154 }
149 155
150 PLUGIN_PRINTF(("PnaclCoordinator: StreamInit successful\n")); 156 PLUGIN_PRINTF(("PnaclCoordinator: StreamInit successful\n"));
151 157
152 // llc process is started. 158 // llc process is started.
153 while(!done_ || data_buffers_.size() > 0) { 159 while(!done_ || data_buffers_.size() > 0) {
154 NaClXMutexLock(&cond_mu_); 160 NaClXMutexLock(&cond_mu_);
155 while(!done_ && data_buffers_.size() == 0) { 161 while(!done_ && data_buffers_.size() == 0) {
156 NaClXCondVarWait(&buffer_cond_, &cond_mu_); 162 NaClXCondVarWait(&buffer_cond_, &cond_mu_);
157 } 163 }
158 PLUGIN_PRINTF(("PnaclTranslateThread awake, done %d, size %d\n", 164 PLUGIN_PRINTF(("PnaclTranslateThread awake, done %d, size %d\n",
159 done_, data_buffers_.size())); 165 done_, data_buffers_.size()));
160 if (data_buffers_.size() > 0) { 166 if (data_buffers_.size() > 0) {
161 std::vector<char> data; 167 std::vector<char> data;
162 data.swap(data_buffers_.front()); 168 data.swap(data_buffers_.front());
163 data_buffers_.pop_front(); 169 data_buffers_.pop_front();
164 NaClXMutexUnlock(&cond_mu_); 170 NaClXMutexUnlock(&cond_mu_);
165 PLUGIN_PRINTF(("StreamChunk\n")); 171 PLUGIN_PRINTF(("StreamChunk\n"));
166 if (!llc_subprocess->InvokeSrpcMethod("StreamChunk", 172 if (!llc_subprocess_->InvokeSrpcMethod("StreamChunk",
167 "C", 173 "C",
168 &params, 174 &params,
169 &data[0], 175 &data[0],
170 data.size())) { 176 data.size())) {
171 TranslateFailed("Compile stream chunk failed."); 177 TranslateFailed("Compile stream chunk failed.");
172 return; 178 return;
173 } 179 }
174 PLUGIN_PRINTF(("StreamChunk Successful\n")); 180 PLUGIN_PRINTF(("StreamChunk Successful\n"));
175 } else { 181 } else {
176 NaClXMutexUnlock(&cond_mu_); 182 NaClXMutexUnlock(&cond_mu_);
177 } 183 }
178 if (SubprocessesShouldDie()) {
179 TranslateFailed("Stopped by coordinator.");
180 return;
181 }
182 } 184 }
183 PLUGIN_PRINTF(("PnaclTranslateThread done with chunks\n")); 185 PLUGIN_PRINTF(("PnaclTranslateThread done with chunks\n"));
184 // Finish llc. 186 // Finish llc.
185 if(!llc_subprocess->InvokeSrpcMethod("StreamEnd", 187 if(!llc_subprocess_->InvokeSrpcMethod("StreamEnd",
186 "", 188 "",
187 &params)) { 189 &params)) {
188 PLUGIN_PRINTF(("PnaclTranslateThread StreamEnd failed\n")); 190 PLUGIN_PRINTF(("PnaclTranslateThread StreamEnd failed\n"));
189 TranslateFailed(params.outs()[3]->arrays.str); 191 if (llc_subprocess_->srpc_client()->GetLastError() ==
192 NACL_SRPC_RESULT_APP_ERROR) {
193 // The error string is only present if the error was sent back from llc
194 TranslateFailed(params.outs()[3]->arrays.str);
195 } else {
196 TranslateFailed("Compile StreamEnd internal error");
197 }
190 return; 198 return;
191 } 199 }
192 // LLC returns values that are used to determine how linking is done. 200 // LLC returns values that are used to determine how linking is done.
193 int is_shared_library = (params.outs()[0]->u.ival != 0); 201 int is_shared_library = (params.outs()[0]->u.ival != 0);
194 nacl::string soname = params.outs()[1]->arrays.str; 202 nacl::string soname = params.outs()[1]->arrays.str;
195 nacl::string lib_dependencies = params.outs()[2]->arrays.str; 203 nacl::string lib_dependencies = params.outs()[2]->arrays.str;
196 PLUGIN_PRINTF(("PnaclCoordinator: compile (translator=%p) succeeded" 204 PLUGIN_PRINTF(("PnaclCoordinator: compile (translator=%p) succeeded"
197 " is_shared_library=%d, soname='%s', lib_dependencies='%s')\n", 205 " is_shared_library=%d, soname='%s', lib_dependencies='%s')\n",
198 this, is_shared_library, soname.c_str(), 206 this, is_shared_library, soname.c_str(),
199 lib_dependencies.c_str())); 207 lib_dependencies.c_str()));
200 208
201 // Shut down the llc subprocess. 209 // Shut down the llc subprocess.
202 RegisterReverseInterface(NULL); 210 NaClXMutexLock(&subprocess_mu_);
203 llc_subprocess.reset(NULL); 211 llc_subprocess_.reset(NULL);
204 if (SubprocessesShouldDie()) { 212 NaClXMutexUnlock(&subprocess_mu_);
205 TranslateFailed("stopped by coordinator.");
206 return;
207 }
208 213
209 if(!RunLdSubprocess(is_shared_library, soname, lib_dependencies)) { 214 if(!RunLdSubprocess(is_shared_library, soname, lib_dependencies)) {
210 return; 215 return;
211 } 216 }
212 pp::Core* core = pp::Module::Get()->core(); 217 pp::Core* core = pp::Module::Get()->core();
213 core->CallOnMainThread(0, report_translate_finished_, PP_OK); 218 core->CallOnMainThread(0, report_translate_finished_, PP_OK);
214 } 219 }
215 220
216 bool PnaclTranslateThread::RunLdSubprocess(int is_shared_library, 221 bool PnaclTranslateThread::RunLdSubprocess(int is_shared_library,
217 const nacl::string& soname, 222 const nacl::string& soname,
218 const nacl::string& lib_dependencies 223 const nacl::string& lib_dependencies
219 ) { 224 ) {
220 ErrorInfo error_info; 225 ErrorInfo error_info;
221 nacl::scoped_ptr<NaClSubprocess> ld_subprocess(
222 StartSubprocess(PnaclUrls::GetLdUrl(), ld_manifest_, &error_info));
223 if (ld_subprocess == NULL) {
224 TranslateFailed("Link process could not be created: " +
225 error_info.message());
226 return false;
227 }
228 // Run LD.
229 SrpcParams params; 226 SrpcParams params;
230
231 // Reset object file for reading first. 227 // Reset object file for reading first.
232 if (!obj_file_->Reset()) { 228 if (!obj_file_->Reset()) {
233 TranslateFailed("Link process could not reset object file"); 229 TranslateFailed("Link process could not reset object file");
234 return false; 230 return false;
235 } 231 }
236 nacl::DescWrapper* ld_in_file = obj_file_->get_wrapper(); 232 nacl::DescWrapper* ld_in_file = obj_file_->get_wrapper();
237 nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper(); 233 nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper();
238 PluginReverseInterface* ld_reverse = 234
239 ld_subprocess->service_runtime()->rev_interface(); 235 {
240 ld_reverse->AddQuotaManagedFile(nexe_file_->identifier(), 236 // Create LD process
241 nexe_file_->write_file_io()); 237 nacl::MutexLocker ml(&subprocess_mu_);
242 RegisterReverseInterface(ld_reverse); 238 ld_subprocess_.reset(
243 if (!ld_subprocess->InvokeSrpcMethod("RunWithDefaultCommandLine", 239 StartSubprocess(PnaclUrls::GetLdUrl(), ld_manifest_, &error_info));
240 if (ld_subprocess_ == NULL) {
241 TranslateFailed("Link process could not be created: " +
242 error_info.message());
243 return false;
244 }
245 PluginReverseInterface* ld_reverse =
246 ld_subprocess_->service_runtime()->rev_interface();
247 ld_reverse->AddQuotaManagedFile(nexe_file_->identifier(),
248 nexe_file_->write_file_io());
249 }
250 // Run LD.
251 if (!ld_subprocess_->InvokeSrpcMethod("RunWithDefaultCommandLine",
244 "hhiss", 252 "hhiss",
245 &params, 253 &params,
246 ld_in_file->desc(), 254 ld_in_file->desc(),
247 ld_out_file->desc(), 255 ld_out_file->desc(),
248 is_shared_library, 256 is_shared_library,
249 soname.c_str(), 257 soname.c_str(),
250 lib_dependencies.c_str())) { 258 lib_dependencies.c_str())) {
251 TranslateFailed("link failed."); 259 TranslateFailed("link failed.");
252 return false; 260 return false;
253 } 261 }
254 PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n", 262 PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n",
255 this)); 263 this));
256 // Shut down the ld subprocess. 264 // Shut down the ld subprocess.
257 RegisterReverseInterface(NULL); 265 NaClXMutexLock(&subprocess_mu_);
258 ld_subprocess.reset(NULL); 266 ld_subprocess_.reset(NULL);
259 if (SubprocessesShouldDie()) { 267 NaClXMutexUnlock(&subprocess_mu_);
260 TranslateFailed("stopped by coordinator.");
261 return false;
262 }
263 return true; 268 return true;
264 } 269 }
265 270
266 void PnaclTranslateThread::TranslateFailed(const nacl::string& error_string) { 271 void PnaclTranslateThread::TranslateFailed(const nacl::string& error_string) {
267 PLUGIN_PRINTF(("PnaclTranslateThread::TranslateFailed (error_string='%s')\n", 272 PLUGIN_PRINTF(("PnaclTranslateThread::TranslateFailed (error_string='%s')\n",
268 error_string.c_str())); 273 error_string.c_str()));
269 pp::Core* core = pp::Module::Get()->core(); 274 pp::Core* core = pp::Module::Get()->core();
270 if (coordinator_error_info_->message().empty()) { 275 if (coordinator_error_info_->message().empty()) {
271 // Only use our message if one hasn't already been set by the coordinator 276 // Only use our message if one hasn't already been set by the coordinator
272 // (e.g. pexe load failed). 277 // (e.g. pexe load failed).
273 coordinator_error_info_->SetReport(ERROR_UNKNOWN, 278 coordinator_error_info_->SetReport(ERROR_UNKNOWN,
274 nacl::string("PnaclCoordinator: ") + 279 nacl::string("PnaclCoordinator: ") +
275 error_string); 280 error_string);
276 } 281 }
277 core->CallOnMainThread(0, report_translate_finished_, PP_ERROR_FAILED); 282 core->CallOnMainThread(0, report_translate_finished_, PP_ERROR_FAILED);
278 } 283 }
279 284
280 // This synchronization method (using the pointer directly in the 285 void PnaclTranslateThread::AbortSubprocesses() {
281 // translation thread, setting a copy here, and calling shutdown on the 286 PLUGIN_PRINTF(("PnaclTranslateThread::AbortSubprocesses\n"));
282 // main thread) is safe only because only the translation thread sets
283 // the copy, and the shutdown method is thread-safe. This method must be
284 // called on the translation thread before any RPCs are called, and called
285 // again with NULL before the object is destroyed.
286 void PnaclTranslateThread::RegisterReverseInterface(
287 PluginReverseInterface *iface) {
288 nacl::MutexLocker ml(&subprocess_mu_);
289 current_rev_interface_ = iface;
290 }
291
292
293 bool PnaclTranslateThread::SubprocessesShouldDie() {
294 nacl::MutexLocker ml(&subprocess_mu_);
295 return subprocesses_should_die_;
296 }
297
298 void PnaclTranslateThread::SetSubprocessesShouldDie() {
299 PLUGIN_PRINTF(("PnaclTranslateThread::SetSubprocessesShouldDie\n"));
300 NaClXMutexLock(&subprocess_mu_); 287 NaClXMutexLock(&subprocess_mu_);
301 subprocesses_should_die_ = true; 288 if (llc_subprocess_ != NULL) llc_subprocess_->service_runtime()->Shutdown();
jvoung (off chromium) 2012/08/02 23:24:10 Since set llc_subprocess is not set to null after,
Derek Schuff 2012/08/02 23:46:45 I *think* so, but it actually goes pretty deep int
302 if (current_rev_interface_) { 289 if (ld_subprocess_ != NULL) ld_subprocess_->service_runtime()->Shutdown();
303 current_rev_interface_->ShutDown();
304 current_rev_interface_ = NULL;
305 }
306 NaClXMutexUnlock(&subprocess_mu_); 290 NaClXMutexUnlock(&subprocess_mu_);
307 nacl::MutexLocker ml(&cond_mu_); 291 nacl::MutexLocker ml(&cond_mu_);
308 done_ = true; 292 done_ = true;
293 // Free all buffered bitcode chunks
294 data_buffers_.clear();
309 NaClXCondVarSignal(&buffer_cond_); 295 NaClXCondVarSignal(&buffer_cond_);
310 } 296 }
311 297
312 PnaclTranslateThread::~PnaclTranslateThread() { 298 PnaclTranslateThread::~PnaclTranslateThread() {
313 PLUGIN_PRINTF(("~PnaclTranslateThread (translate_thread=%p)\n", this)); 299 PLUGIN_PRINTF(("~PnaclTranslateThread (translate_thread=%p)\n", this));
314 SetSubprocessesShouldDie(); 300 AbortSubprocesses();
jvoung (off chromium) 2012/08/02 23:24:10 AbortSubprocesses() is called from multiple destru
Derek Schuff 2012/08/02 23:46:45 Other than potentially service_runtime Shutdown (a
315 NaClThreadJoin(translate_thread_.get()); 301 NaClThreadJoin(translate_thread_.get());
316 PLUGIN_PRINTF(("~PnaclTranslateThread joined\n")); 302 PLUGIN_PRINTF(("~PnaclTranslateThread joined\n"));
303 NaClCondVarDtor(&buffer_cond_);
304 NaClMutexDtor(&cond_mu_);
317 NaClMutexDtor(&subprocess_mu_); 305 NaClMutexDtor(&subprocess_mu_);
318 } 306 }
319 307
320 } // namespace plugin 308 } // namespace plugin
OLDNEW
« no previous file with comments | « ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h ('k') | ppapi/native_client/src/trusted/plugin/srpc_client.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698