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

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