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 |