OLD | NEW |
---|---|
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 "components/nacl/renderer/plugin/pnacl_translate_thread.h" | 5 #include "components/nacl/renderer/plugin/pnacl_translate_thread.h" |
6 | 6 |
7 #include <iterator> | 7 #include <iterator> |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "components/nacl/renderer/plugin/plugin.h" | 11 #include "components/nacl/renderer/plugin/plugin.h" |
12 #include "components/nacl/renderer/plugin/plugin_error.h" | 12 #include "components/nacl/renderer/plugin/plugin_error.h" |
13 #include "components/nacl/renderer/plugin/srpc_params.h" | 13 #include "components/nacl/renderer/plugin/srpc_params.h" |
14 #include "components/nacl/renderer/plugin/temporary_file.h" | 14 #include "components/nacl/renderer/plugin/temporary_file.h" |
15 #include "components/nacl/renderer/plugin/utility.h" | 15 #include "components/nacl/renderer/plugin/utility.h" |
16 #include "content/public/common/sandbox_init.h" | |
16 #include "native_client/src/shared/platform/nacl_sync_raii.h" | 17 #include "native_client/src/shared/platform/nacl_sync_raii.h" |
17 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" | 18 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" |
19 #include "ppapi/c/ppb_file_io.h" | |
18 #include "ppapi/cpp/var.h" | 20 #include "ppapi/cpp/var.h" |
21 #include "ppapi/proxy/ppapi_messages.h" | |
19 | 22 |
20 namespace plugin { | 23 namespace plugin { |
21 namespace { | 24 namespace { |
22 | 25 |
23 template <typename Val> | 26 template <typename Val> |
24 std::string MakeCommandLineArg(const char* key, const Val val) { | 27 std::string MakeCommandLineArg(const char* key, const Val val) { |
25 std::stringstream ss; | 28 std::stringstream ss; |
26 ss << key << val; | 29 ss << key << val; |
27 return ss.str(); | 30 return ss.str(); |
28 } | 31 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
77 : compiler_subprocess_(NULL), | 80 : compiler_subprocess_(NULL), |
78 ld_subprocess_(NULL), | 81 ld_subprocess_(NULL), |
79 compiler_subprocess_active_(false), | 82 compiler_subprocess_active_(false), |
80 ld_subprocess_active_(false), | 83 ld_subprocess_active_(false), |
81 done_(false), | 84 done_(false), |
82 compile_time_(0), | 85 compile_time_(0), |
83 obj_files_(NULL), | 86 obj_files_(NULL), |
84 num_threads_(0), | 87 num_threads_(0), |
85 nexe_file_(NULL), | 88 nexe_file_(NULL), |
86 coordinator_error_info_(NULL), | 89 coordinator_error_info_(NULL), |
87 coordinator_(NULL) { | 90 coordinator_(NULL), |
91 ld_channel_peer_pid_(base::kNullProcessId) { | |
88 NaClXMutexCtor(&subprocess_mu_); | 92 NaClXMutexCtor(&subprocess_mu_); |
89 NaClXMutexCtor(&cond_mu_); | 93 NaClXMutexCtor(&cond_mu_); |
90 NaClXCondVarCtor(&buffer_cond_); | 94 NaClXCondVarCtor(&buffer_cond_); |
91 } | 95 } |
92 | 96 |
93 void PnaclTranslateThread::SetupState( | 97 void PnaclTranslateThread::SetupState( |
94 const pp::CompletionCallback& finish_callback, | 98 const pp::CompletionCallback& finish_callback, |
95 NaClSubprocess* compiler_subprocess, | 99 NaClSubprocess* compiler_subprocess, |
96 NaClSubprocess* ld_subprocess, | 100 NaClSubprocess* ld_subprocess, |
97 const std::vector<TempFile*>* obj_files, | 101 const std::vector<TempFile*>* obj_files, |
(...skipping 19 matching lines...) Expand all Loading... | |
117 report_translate_finished_ = finish_callback; | 121 report_translate_finished_ = finish_callback; |
118 } | 122 } |
119 | 123 |
120 void PnaclTranslateThread::RunCompile( | 124 void PnaclTranslateThread::RunCompile( |
121 const pp::CompletionCallback& compile_finished_callback) { | 125 const pp::CompletionCallback& compile_finished_callback) { |
122 PLUGIN_PRINTF(("PnaclTranslateThread::RunCompile)\n")); | 126 PLUGIN_PRINTF(("PnaclTranslateThread::RunCompile)\n")); |
123 DCHECK(started()); | 127 DCHECK(started()); |
124 DCHECK(compiler_subprocess_->service_runtime()); | 128 DCHECK(compiler_subprocess_->service_runtime()); |
125 compiler_subprocess_active_ = true; | 129 compiler_subprocess_active_ = true; |
126 | 130 |
131 // Free this IPC channel now to make sure that it does not get freed on | |
132 // the child thread when the child thread calls Shutdown(). | |
bbudge
2015/12/17 21:17:11
I'm assuming this is temporary, until you remove S
Mark Seaborn
2015/12/21 22:58:50
Yes. Done.
| |
133 compiler_subprocess_->service_runtime()->TakeTranslatorChannel(); | |
134 | |
127 compile_finished_callback_ = compile_finished_callback; | 135 compile_finished_callback_ = compile_finished_callback; |
128 translate_thread_.reset(new NaClThread); | 136 translate_thread_.reset(new NaClThread); |
129 if (translate_thread_ == NULL) { | 137 if (translate_thread_ == NULL) { |
130 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, | 138 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, |
131 "could not allocate thread struct."); | 139 "could not allocate thread struct."); |
132 return; | 140 return; |
133 } | 141 } |
134 const int32_t kArbitraryStackSize = 128 * 1024; | 142 const int32_t kArbitraryStackSize = 128 * 1024; |
135 if (!NaClThreadCreateJoinable(translate_thread_.get(), DoCompileThread, this, | 143 if (!NaClThreadCreateJoinable(translate_thread_.get(), DoCompileThread, this, |
136 kArbitraryStackSize)) { | 144 kArbitraryStackSize)) { |
137 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, | 145 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, |
138 "could not create thread."); | 146 "could not create thread."); |
139 translate_thread_.reset(NULL); | 147 translate_thread_.reset(NULL); |
140 } | 148 } |
141 } | 149 } |
142 | 150 |
143 void PnaclTranslateThread::RunLink() { | 151 void PnaclTranslateThread::RunLink() { |
144 PLUGIN_PRINTF(("PnaclTranslateThread::RunLink)\n")); | 152 PLUGIN_PRINTF(("PnaclTranslateThread::RunLink)\n")); |
145 DCHECK(started()); | 153 DCHECK(started()); |
146 DCHECK(ld_subprocess_->service_runtime()); | 154 DCHECK(ld_subprocess_->service_runtime()); |
147 ld_subprocess_active_ = true; | 155 ld_subprocess_active_ = true; |
148 | 156 |
157 // Take ownership of this IPC channel to make sure that it does not get | |
158 // freed on the child thread when the child thread calls Shutdown(). | |
159 ld_channel_ = ld_subprocess_->service_runtime()->TakeTranslatorChannel(); | |
160 // ld_channel_ is a IPC::SyncChannel, which is not thread-safe and cannot be | |
161 // used directly by the child thread, so create a SyncMessageFilter which | |
162 // can be used by the child thread. | |
163 ld_channel_filter_ = ld_channel_->CreateSyncMessageFilter(); | |
164 // Make a copy of the process ID, again to avoid any thread-safety issues | |
165 // involved in accessing ld_subprocess_ on the child thread. | |
166 ld_channel_peer_pid_ = ld_subprocess_->service_runtime()->get_process_id(); | |
167 | |
149 // Tear down the previous thread. | 168 // Tear down the previous thread. |
150 // TODO(jvoung): Use base/threading or something where we can have a | 169 // TODO(jvoung): Use base/threading or something where we can have a |
151 // persistent thread and easily post tasks to that persistent thread. | 170 // persistent thread and easily post tasks to that persistent thread. |
152 NaClThreadJoin(translate_thread_.get()); | 171 NaClThreadJoin(translate_thread_.get()); |
153 translate_thread_.reset(new NaClThread); | 172 translate_thread_.reset(new NaClThread); |
154 if (translate_thread_ == NULL) { | 173 if (translate_thread_ == NULL) { |
155 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, | 174 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, |
156 "could not allocate thread struct."); | 175 "could not allocate thread struct."); |
157 return; | 176 return; |
158 } | 177 } |
(...skipping 18 matching lines...) Expand all Loading... | |
177 NaClXMutexUnlock(&cond_mu_); | 196 NaClXMutexUnlock(&cond_mu_); |
178 } | 197 } |
179 | 198 |
180 void PnaclTranslateThread::EndStream() { | 199 void PnaclTranslateThread::EndStream() { |
181 NaClXMutexLock(&cond_mu_); | 200 NaClXMutexLock(&cond_mu_); |
182 done_ = true; | 201 done_ = true; |
183 NaClXCondVarSignal(&buffer_cond_); | 202 NaClXCondVarSignal(&buffer_cond_); |
184 NaClXMutexUnlock(&cond_mu_); | 203 NaClXMutexUnlock(&cond_mu_); |
185 } | 204 } |
186 | 205 |
206 ppapi::proxy::SerializedHandle PnaclTranslateThread::GetHandleForSubprocess( | |
207 TempFile* file, int32_t open_flags) { | |
208 IPC::PlatformFileForTransit file_for_transit; | |
209 | |
210 #if defined(OS_WIN) | |
211 if (!content::BrokerDuplicateHandle( | |
212 file->GetFileHandle(), | |
213 ld_channel_peer_pid_, | |
214 &file_for_transit, | |
215 0, // desired_access is 0 since we're using DUPLICATE_SAME_ACCESS. | |
216 DUPLICATE_SAME_ACCESS)) { | |
217 return ppapi::proxy::SerializedHandle(); | |
218 } | |
219 #else | |
220 file_for_transit = base::FileDescriptor(dup(file->GetFileHandle()), true); | |
221 #endif | |
222 | |
223 // Using 0 disables any use of quota enforcement for this file handle. | |
224 PP_Resource file_io = 0; | |
225 | |
226 ppapi::proxy::SerializedHandle handle; | |
227 handle.set_file_handle(file_for_transit, open_flags, file_io); | |
228 return handle; | |
229 } | |
230 | |
187 void WINAPI PnaclTranslateThread::DoCompileThread(void* arg) { | 231 void WINAPI PnaclTranslateThread::DoCompileThread(void* arg) { |
188 PnaclTranslateThread* translator = | 232 PnaclTranslateThread* translator = |
189 reinterpret_cast<PnaclTranslateThread*>(arg); | 233 reinterpret_cast<PnaclTranslateThread*>(arg); |
190 translator->DoCompile(); | 234 translator->DoCompile(); |
191 } | 235 } |
192 | 236 |
193 void PnaclTranslateThread::DoCompile() { | 237 void PnaclTranslateThread::DoCompile() { |
194 { | 238 { |
195 nacl::MutexLocker ml(&subprocess_mu_); | 239 nacl::MutexLocker ml(&subprocess_mu_); |
196 // If the main thread asked us to exit in between starting the thread | 240 // If the main thread asked us to exit in between starting the thread |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
339 translator->DoLink(); | 383 translator->DoLink(); |
340 } | 384 } |
341 | 385 |
342 void PnaclTranslateThread::DoLink() { | 386 void PnaclTranslateThread::DoLink() { |
343 { | 387 { |
344 nacl::MutexLocker ml(&subprocess_mu_); | 388 nacl::MutexLocker ml(&subprocess_mu_); |
345 // If the main thread asked us to exit in between starting the thread | 389 // If the main thread asked us to exit in between starting the thread |
346 // and now, just leave now. | 390 // and now, just leave now. |
347 if (!ld_subprocess_active_) | 391 if (!ld_subprocess_active_) |
348 return; | 392 return; |
349 // Now that we are in helper thread, we can do the the blocking | 393 } |
350 // StartSrpcServices operation. | 394 |
351 if (!ld_subprocess_->StartSrpcServices()) { | 395 // Reset object files for reading first. We do this before duplicating |
352 TranslateFailed( | 396 // handles/FDs to prevent any handle/FD leaks in case any of the Reset() |
353 PP_NACL_ERROR_SRPC_CONNECTION_FAIL, | 397 // calls fail. |
354 "SRPC connection failure for " + ld_subprocess_->description()); | 398 for (TempFile* obj_file : *obj_files_) { |
399 if (!obj_file->Reset()) { | |
400 TranslateFailed(PP_NACL_ERROR_PNACL_LD_SETUP, | |
401 "Link process could not reset object file"); | |
355 return; | 402 return; |
356 } | 403 } |
357 } | 404 } |
358 | 405 |
359 SrpcParams params; | 406 ppapi::proxy::SerializedHandle nexe_file = |
360 std::vector<nacl::DescWrapper*> ld_in_files; | 407 GetHandleForSubprocess(nexe_file_, PP_FILEOPENFLAG_WRITE); |
361 size_t i; | 408 std::vector<ppapi::proxy::SerializedHandle> ld_input_files; |
362 for (i = 0; i < obj_files_->size(); i++) { | 409 for (TempFile* obj_file : *obj_files_) { |
363 // Reset object file for reading first. | 410 ld_input_files.push_back( |
364 if (!(*obj_files_)[i]->Reset()) { | 411 GetHandleForSubprocess(obj_file, PP_FILEOPENFLAG_READ)); |
365 TranslateFailed(PP_NACL_ERROR_PNACL_LD_SETUP, | |
366 "Link process could not reset object file"); | |
367 } | |
368 ld_in_files.push_back((*obj_files_)[i]->read_wrapper()); | |
369 } | 412 } |
370 for (; i < PnaclCoordinator::kMaxTranslatorObjectFiles; i++) | |
371 ld_in_files.push_back(invalid_desc_wrapper_); | |
372 | 413 |
373 nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper(); | |
374 int64_t link_start_time = NaClGetTimeOfDayMicroseconds(); | 414 int64_t link_start_time = NaClGetTimeOfDayMicroseconds(); |
375 // Run LD. | 415 bool success = false; |
376 bool success = ld_subprocess_->InvokeSrpcMethod( | 416 bool sent = ld_channel_filter_->Send( |
377 "RunWithSplit", | 417 new PpapiMsg_PnaclTranslatorLink(ld_input_files, nexe_file, &success)); |
378 "ihhhhhhhhhhhhhhhhh", | 418 if (!sent) { |
379 ¶ms, | 419 TranslateFailed(PP_NACL_ERROR_PNACL_LD_INTERNAL, |
380 static_cast<int>(obj_files_->size()), | 420 "link failed: reply not received from linker."); |
381 ld_in_files[0]->desc(), | 421 return; |
382 ld_in_files[1]->desc(), | 422 } |
383 ld_in_files[2]->desc(), | |
384 ld_in_files[3]->desc(), | |
385 ld_in_files[4]->desc(), | |
386 ld_in_files[5]->desc(), | |
387 ld_in_files[6]->desc(), | |
388 ld_in_files[7]->desc(), | |
389 ld_in_files[8]->desc(), | |
390 ld_in_files[9]->desc(), | |
391 ld_in_files[10]->desc(), | |
392 ld_in_files[11]->desc(), | |
393 ld_in_files[12]->desc(), | |
394 ld_in_files[13]->desc(), | |
395 ld_in_files[14]->desc(), | |
396 ld_in_files[15]->desc(), | |
397 ld_out_file->desc()); | |
398 if (!success) { | 423 if (!success) { |
399 TranslateFailed(PP_NACL_ERROR_PNACL_LD_INTERNAL, | 424 TranslateFailed(PP_NACL_ERROR_PNACL_LD_INTERNAL, |
400 "link failed."); | 425 "link failed: linker returned failure status."); |
401 return; | 426 return; |
402 } | 427 } |
428 | |
403 GetNaClInterface()->LogTranslateTime( | 429 GetNaClInterface()->LogTranslateTime( |
404 "NaCl.Perf.PNaClLoadTime.LinkTime", | 430 "NaCl.Perf.PNaClLoadTime.LinkTime", |
405 NaClGetTimeOfDayMicroseconds() - link_start_time); | 431 NaClGetTimeOfDayMicroseconds() - link_start_time); |
406 PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n", | 432 PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n", |
407 this)); | 433 this)); |
408 | 434 |
409 // Shut down the ld subprocess. | 435 // Shut down the ld subprocess. |
410 NaClXMutexLock(&subprocess_mu_); | 436 NaClXMutexLock(&subprocess_mu_); |
411 ld_subprocess_active_ = false; | 437 ld_subprocess_active_ = false; |
412 ld_subprocess_->Shutdown(); | 438 ld_subprocess_->Shutdown(); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
459 AbortSubprocesses(); | 485 AbortSubprocesses(); |
460 if (translate_thread_ != NULL) | 486 if (translate_thread_ != NULL) |
461 NaClThreadJoin(translate_thread_.get()); | 487 NaClThreadJoin(translate_thread_.get()); |
462 PLUGIN_PRINTF(("~PnaclTranslateThread joined\n")); | 488 PLUGIN_PRINTF(("~PnaclTranslateThread joined\n")); |
463 NaClCondVarDtor(&buffer_cond_); | 489 NaClCondVarDtor(&buffer_cond_); |
464 NaClMutexDtor(&cond_mu_); | 490 NaClMutexDtor(&cond_mu_); |
465 NaClMutexDtor(&subprocess_mu_); | 491 NaClMutexDtor(&subprocess_mu_); |
466 } | 492 } |
467 | 493 |
468 } // namespace plugin | 494 } // namespace plugin |
OLD | NEW |