Chromium Code Reviews| 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 |