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(). | |
| 133 // TODO(mseaborn): Convert DoCompile() to using Chrome IPC instead of SRPC, | |
| 134 // the same way DoLink() has been converted. Then we will use this IPC | |
| 135 // channel instead of just freeing it here. | |
| 136 compiler_subprocess_->service_runtime()->TakeTranslatorChannel(); | |
| 137 | |
| 127 compile_finished_callback_ = compile_finished_callback; | 138 compile_finished_callback_ = compile_finished_callback; |
| 128 translate_thread_.reset(new NaClThread); | 139 translate_thread_.reset(new NaClThread); |
| 129 if (translate_thread_ == NULL) { | 140 if (translate_thread_ == NULL) { |
| 130 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, | 141 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, |
| 131 "could not allocate thread struct."); | 142 "could not allocate thread struct."); |
| 132 return; | 143 return; |
| 133 } | 144 } |
| 134 const int32_t kArbitraryStackSize = 128 * 1024; | 145 const int32_t kArbitraryStackSize = 128 * 1024; |
| 135 if (!NaClThreadCreateJoinable(translate_thread_.get(), DoCompileThread, this, | 146 if (!NaClThreadCreateJoinable(translate_thread_.get(), DoCompileThread, this, |
| 136 kArbitraryStackSize)) { | 147 kArbitraryStackSize)) { |
| 137 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, | 148 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, |
| 138 "could not create thread."); | 149 "could not create thread."); |
| 139 translate_thread_.reset(NULL); | 150 translate_thread_.reset(NULL); |
| 140 } | 151 } |
| 141 } | 152 } |
| 142 | 153 |
| 143 void PnaclTranslateThread::RunLink() { | 154 void PnaclTranslateThread::RunLink() { |
| 144 PLUGIN_PRINTF(("PnaclTranslateThread::RunLink)\n")); | 155 PLUGIN_PRINTF(("PnaclTranslateThread::RunLink)\n")); |
| 145 DCHECK(started()); | 156 DCHECK(started()); |
| 146 DCHECK(ld_subprocess_->service_runtime()); | 157 DCHECK(ld_subprocess_->service_runtime()); |
| 147 ld_subprocess_active_ = true; | 158 ld_subprocess_active_ = true; |
| 148 | 159 |
| 160 // Take ownership of this IPC channel to make sure that it does not get | |
| 161 // freed on the child thread when the child thread calls Shutdown(). | |
| 162 ld_channel_ = ld_subprocess_->service_runtime()->TakeTranslatorChannel(); | |
| 163 // ld_channel_ is a IPC::SyncChannel, which is not thread-safe and cannot be | |
| 164 // used directly by the child thread, so create a SyncMessageFilter which | |
| 165 // can be used by the child thread. | |
| 166 ld_channel_filter_ = ld_channel_->CreateSyncMessageFilter(); | |
| 167 // Make a copy of the process ID, again to avoid any thread-safety issues | |
| 168 // involved in accessing ld_subprocess_ on the child thread. | |
| 169 ld_channel_peer_pid_ = ld_subprocess_->service_runtime()->get_process_id(); | |
| 170 | |
| 149 // Tear down the previous thread. | 171 // Tear down the previous thread. |
| 150 // TODO(jvoung): Use base/threading or something where we can have a | 172 // TODO(jvoung): Use base/threading or something where we can have a |
| 151 // persistent thread and easily post tasks to that persistent thread. | 173 // persistent thread and easily post tasks to that persistent thread. |
| 152 NaClThreadJoin(translate_thread_.get()); | 174 NaClThreadJoin(translate_thread_.get()); |
| 153 translate_thread_.reset(new NaClThread); | 175 translate_thread_.reset(new NaClThread); |
| 154 if (translate_thread_ == NULL) { | 176 if (translate_thread_ == NULL) { |
| 155 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, | 177 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, |
| 156 "could not allocate thread struct."); | 178 "could not allocate thread struct."); |
| 157 return; | 179 return; |
| 158 } | 180 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 177 NaClXMutexUnlock(&cond_mu_); | 199 NaClXMutexUnlock(&cond_mu_); |
| 178 } | 200 } |
| 179 | 201 |
| 180 void PnaclTranslateThread::EndStream() { | 202 void PnaclTranslateThread::EndStream() { |
| 181 NaClXMutexLock(&cond_mu_); | 203 NaClXMutexLock(&cond_mu_); |
| 182 done_ = true; | 204 done_ = true; |
| 183 NaClXCondVarSignal(&buffer_cond_); | 205 NaClXCondVarSignal(&buffer_cond_); |
| 184 NaClXMutexUnlock(&cond_mu_); | 206 NaClXMutexUnlock(&cond_mu_); |
| 185 } | 207 } |
| 186 | 208 |
| 209 ppapi::proxy::SerializedHandle PnaclTranslateThread::GetHandleForSubprocess( | |
| 210 TempFile* file, int32_t open_flags) { | |
| 211 IPC::PlatformFileForTransit file_for_transit; | |
| 212 | |
| 213 #if defined(OS_WIN) | |
| 214 if (!content::BrokerDuplicateHandle( | |
|
Will Harris
2015/12/22 05:12:08
Is another BrokerAddTargetPeer required here for t
| |
| 215 file->GetFileHandle(), | |
| 216 ld_channel_peer_pid_, | |
| 217 &file_for_transit, | |
| 218 0, // desired_access is 0 since we're using DUPLICATE_SAME_ACCESS. | |
| 219 DUPLICATE_SAME_ACCESS)) { | |
| 220 return ppapi::proxy::SerializedHandle(); | |
| 221 } | |
| 222 #else | |
| 223 file_for_transit = base::FileDescriptor(dup(file->GetFileHandle()), true); | |
| 224 #endif | |
| 225 | |
| 226 // Using 0 disables any use of quota enforcement for this file handle. | |
| 227 PP_Resource file_io = 0; | |
| 228 | |
| 229 ppapi::proxy::SerializedHandle handle; | |
| 230 handle.set_file_handle(file_for_transit, open_flags, file_io); | |
| 231 return handle; | |
| 232 } | |
| 233 | |
| 187 void WINAPI PnaclTranslateThread::DoCompileThread(void* arg) { | 234 void WINAPI PnaclTranslateThread::DoCompileThread(void* arg) { |
| 188 PnaclTranslateThread* translator = | 235 PnaclTranslateThread* translator = |
| 189 reinterpret_cast<PnaclTranslateThread*>(arg); | 236 reinterpret_cast<PnaclTranslateThread*>(arg); |
| 190 translator->DoCompile(); | 237 translator->DoCompile(); |
| 191 } | 238 } |
| 192 | 239 |
| 193 void PnaclTranslateThread::DoCompile() { | 240 void PnaclTranslateThread::DoCompile() { |
| 194 { | 241 { |
| 195 nacl::MutexLocker ml(&subprocess_mu_); | 242 nacl::MutexLocker ml(&subprocess_mu_); |
| 196 // If the main thread asked us to exit in between starting the thread | 243 // 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(); | 386 translator->DoLink(); |
| 340 } | 387 } |
| 341 | 388 |
| 342 void PnaclTranslateThread::DoLink() { | 389 void PnaclTranslateThread::DoLink() { |
| 343 { | 390 { |
| 344 nacl::MutexLocker ml(&subprocess_mu_); | 391 nacl::MutexLocker ml(&subprocess_mu_); |
| 345 // If the main thread asked us to exit in between starting the thread | 392 // If the main thread asked us to exit in between starting the thread |
| 346 // and now, just leave now. | 393 // and now, just leave now. |
| 347 if (!ld_subprocess_active_) | 394 if (!ld_subprocess_active_) |
| 348 return; | 395 return; |
| 349 // Now that we are in helper thread, we can do the the blocking | 396 } |
| 350 // StartSrpcServices operation. | 397 |
| 351 if (!ld_subprocess_->StartSrpcServices()) { | 398 // Reset object files for reading first. We do this before duplicating |
| 352 TranslateFailed( | 399 // handles/FDs to prevent any handle/FD leaks in case any of the Reset() |
| 353 PP_NACL_ERROR_SRPC_CONNECTION_FAIL, | 400 // calls fail. |
| 354 "SRPC connection failure for " + ld_subprocess_->description()); | 401 for (TempFile* obj_file : *obj_files_) { |
| 402 if (!obj_file->Reset()) { | |
| 403 TranslateFailed(PP_NACL_ERROR_PNACL_LD_SETUP, | |
| 404 "Link process could not reset object file"); | |
| 355 return; | 405 return; |
| 356 } | 406 } |
| 357 } | 407 } |
| 358 | 408 |
| 359 SrpcParams params; | 409 ppapi::proxy::SerializedHandle nexe_file = |
| 360 std::vector<nacl::DescWrapper*> ld_in_files; | 410 GetHandleForSubprocess(nexe_file_, PP_FILEOPENFLAG_WRITE); |
| 361 size_t i; | 411 std::vector<ppapi::proxy::SerializedHandle> ld_input_files; |
| 362 for (i = 0; i < obj_files_->size(); i++) { | 412 for (TempFile* obj_file : *obj_files_) { |
| 363 // Reset object file for reading first. | 413 ld_input_files.push_back( |
| 364 if (!(*obj_files_)[i]->Reset()) { | 414 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 } | 415 } |
| 370 for (; i < PnaclCoordinator::kMaxTranslatorObjectFiles; i++) | |
| 371 ld_in_files.push_back(invalid_desc_wrapper_); | |
| 372 | 416 |
| 373 nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper(); | |
| 374 int64_t link_start_time = NaClGetTimeOfDayMicroseconds(); | 417 int64_t link_start_time = NaClGetTimeOfDayMicroseconds(); |
| 375 // Run LD. | 418 bool success = false; |
| 376 bool success = ld_subprocess_->InvokeSrpcMethod( | 419 bool sent = ld_channel_filter_->Send( |
| 377 "RunWithSplit", | 420 new PpapiMsg_PnaclTranslatorLink(ld_input_files, nexe_file, &success)); |
| 378 "ihhhhhhhhhhhhhhhhh", | 421 if (!sent) { |
| 379 ¶ms, | 422 TranslateFailed(PP_NACL_ERROR_PNACL_LD_INTERNAL, |
| 380 static_cast<int>(obj_files_->size()), | 423 "link failed: reply not received from linker."); |
| 381 ld_in_files[0]->desc(), | 424 return; |
| 382 ld_in_files[1]->desc(), | 425 } |
| 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) { | 426 if (!success) { |
| 399 TranslateFailed(PP_NACL_ERROR_PNACL_LD_INTERNAL, | 427 TranslateFailed(PP_NACL_ERROR_PNACL_LD_INTERNAL, |
| 400 "link failed."); | 428 "link failed: linker returned failure status."); |
| 401 return; | 429 return; |
| 402 } | 430 } |
| 431 | |
| 403 GetNaClInterface()->LogTranslateTime( | 432 GetNaClInterface()->LogTranslateTime( |
| 404 "NaCl.Perf.PNaClLoadTime.LinkTime", | 433 "NaCl.Perf.PNaClLoadTime.LinkTime", |
| 405 NaClGetTimeOfDayMicroseconds() - link_start_time); | 434 NaClGetTimeOfDayMicroseconds() - link_start_time); |
| 406 PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n", | 435 PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n", |
| 407 this)); | 436 this)); |
| 408 | 437 |
| 409 // Shut down the ld subprocess. | 438 // Shut down the ld subprocess. |
| 410 NaClXMutexLock(&subprocess_mu_); | 439 NaClXMutexLock(&subprocess_mu_); |
| 411 ld_subprocess_active_ = false; | 440 ld_subprocess_active_ = false; |
| 412 ld_subprocess_->Shutdown(); | 441 ld_subprocess_->Shutdown(); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 459 AbortSubprocesses(); | 488 AbortSubprocesses(); |
| 460 if (translate_thread_ != NULL) | 489 if (translate_thread_ != NULL) |
| 461 NaClThreadJoin(translate_thread_.get()); | 490 NaClThreadJoin(translate_thread_.get()); |
| 462 PLUGIN_PRINTF(("~PnaclTranslateThread joined\n")); | 491 PLUGIN_PRINTF(("~PnaclTranslateThread joined\n")); |
| 463 NaClCondVarDtor(&buffer_cond_); | 492 NaClCondVarDtor(&buffer_cond_); |
| 464 NaClMutexDtor(&cond_mu_); | 493 NaClMutexDtor(&cond_mu_); |
| 465 NaClMutexDtor(&subprocess_mu_); | 494 NaClMutexDtor(&subprocess_mu_); |
| 466 } | 495 } |
| 467 | 496 |
| 468 } // namespace plugin | 497 } // namespace plugin |
| OLD | NEW |