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 #ifdef _MSC_VER | 5 #ifdef _MSC_VER |
6 // Do not warn about use of std::copy with raw pointers. | 6 // Do not warn about use of std::copy with raw pointers. |
7 #pragma warning(disable : 4996) | 7 #pragma warning(disable : 4996) |
8 #endif | 8 #endif |
9 | 9 |
10 #include "ppapi/native_client/src/trusted/plugin/plugin.h" | 10 #include "ppapi/native_client/src/trusted/plugin/plugin.h" |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 // Log the status codes in rough buckets - 1XX, 2XX, etc. | 279 // Log the status codes in rough buckets - 1XX, 2XX, etc. |
280 int sample = status / 100; | 280 int sample = status / 100; |
281 // HTTP status codes only go up to 5XX, using "6" to indicate an internal | 281 // HTTP status codes only go up to 5XX, using "6" to indicate an internal |
282 // error. | 282 // error. |
283 // Note: installed files may have "0" for a status code. | 283 // Note: installed files may have "0" for a status code. |
284 if (status < 0 || status >= 600) | 284 if (status < 0 || status >= 600) |
285 sample = 6; | 285 sample = 6; |
286 HistogramEnumerate(name, sample, 7, 6); | 286 HistogramEnumerate(name, sample, 7, 6); |
287 } | 287 } |
288 | 288 |
289 bool Plugin::LoadNaClModuleCommon(nacl::DescWrapper* wrapper, | 289 void Plugin::StartSelLdrOnMainThread(int32_t pp_error, |
290 NaClSubprocess* subprocess, | 290 ServiceRuntime* service_runtime, |
291 const Manifest* manifest, | 291 const SelLdrStartParams& params, |
292 bool should_report_uma, | 292 PP_CompletionCallback callback) { |
293 const SelLdrStartParams& params, | 293 service_runtime->StartSelLdr(params, callback); |
294 const pp::CompletionCallback& init_done_cb, | 294 } |
295 const pp::CompletionCallback& crash_cb) { | 295 |
296 ErrorInfo error_info; | 296 void Plugin::SignalStartSelLdrDone(int32_t pp_error, |
297 ServiceRuntime* new_service_runtime = | 297 ServiceRuntime* service_runtime) { |
298 new ServiceRuntime(this, manifest, should_report_uma, init_done_cb, | 298 PLUGIN_PRINTF(("Plugin::SignalStartSelLdrDone (this=%p, pp_error=%" |
299 crash_cb); | 299 NACL_PRId32 ")\n", static_cast<void*>(this), pp_error)); |
300 subprocess->set_service_runtime(new_service_runtime); | 300 start_sel_ldr_success_ = (pp_error == PP_OK); |
| 301 service_runtime->SignalStartSelLdrDone(); |
| 302 } |
| 303 |
| 304 bool Plugin::LoadNaClModuleFromBackgroundThread( |
| 305 nacl::DescWrapper* wrapper, |
| 306 NaClSubprocess* subprocess, |
| 307 const Manifest* manifest, |
| 308 const SelLdrStartParams& params) { |
| 309 ServiceRuntime* service_runtime = |
| 310 new ServiceRuntime(this, manifest, false, pp::BlockUntilComplete(), |
| 311 pp::BlockUntilComplete()); |
| 312 subprocess->set_service_runtime(service_runtime); |
301 PLUGIN_PRINTF(("Plugin::LoadNaClModuleCommon (service_runtime=%p)\n", | 313 PLUGIN_PRINTF(("Plugin::LoadNaClModuleCommon (service_runtime=%p)\n", |
302 static_cast<void*>(new_service_runtime))); | 314 static_cast<void*>(service_runtime))); |
303 if (should_report_uma && NULL == new_service_runtime) { | 315 if (NULL == service_runtime) { |
304 error_info.SetReport( | |
305 ERROR_SEL_LDR_INIT, | |
306 "sel_ldr init failure " + subprocess->description()); | |
307 ReportLoadError(error_info); | |
308 return false; | 316 return false; |
309 } | 317 } |
310 | 318 |
311 // Now start the SelLdr instance. This must be created on the main thread. | 319 // Now start the SelLdr instance. This must be created on the main thread. |
312 pp::Core* core = pp::Module::Get()->core(); | 320 pp::Core* core = pp::Module::Get()->core(); |
313 bool service_runtime_started; | 321 pp::CompletionCallback connected_callback = |
314 if (core->IsMainThread()) { | 322 callback_factory_.NewCallback(&Plugin::SignalStartSelLdrDone, |
315 StartSelLdrOnMainThread(PP_OK, new_service_runtime, params, | 323 service_runtime); |
316 &service_runtime_started); | 324 pp::CompletionCallback callback = callback_factory_.NewCallback( |
317 } else { | 325 &Plugin::StartSelLdrOnMainThread, service_runtime, params, |
318 pp::CompletionCallback callback = | 326 connected_callback.pp_completion_callback()); |
319 callback_factory_.NewCallback(&Plugin::StartSelLdrOnMainThread, | 327 core->CallOnMainThread(0, callback, 0); |
320 new_service_runtime, params, | 328 service_runtime->WaitForSelLdrStart(); |
321 &service_runtime_started); | 329 if (!start_sel_ldr_success_) { |
322 core->CallOnMainThread(0, callback, 0); | |
323 new_service_runtime->WaitForSelLdrStart(); | |
324 } | |
325 PLUGIN_PRINTF(("Plugin::LoadNaClModuleCommon (service_runtime_started=%d)\n", | |
326 service_runtime_started)); | |
327 if (!service_runtime_started) { | |
328 return false; | 330 return false; |
329 } | 331 } |
330 | 332 |
331 // Now actually load the nexe, which can happen on a background thread. | 333 // Now actually load the nexe, which can happen on a background thread. |
332 bool nexe_loaded = new_service_runtime->LoadNexeAndStart(wrapper, | 334 bool nexe_loaded = service_runtime->LoadNexeAndStart( |
333 crash_cb); | 335 wrapper, pp::BlockUntilComplete()); |
334 PLUGIN_PRINTF(("Plugin::LoadNaClModuleCommon (nexe_loaded=%d)\n", | 336 PLUGIN_PRINTF(("Plugin::LoadNaClModuleCommon (nexe_loaded=%d)\n", |
335 nexe_loaded)); | 337 nexe_loaded)); |
336 return nexe_loaded; | 338 return nexe_loaded; |
337 } | 339 } |
338 | 340 |
339 void Plugin::StartSelLdrOnMainThread(int32_t pp_error, | |
340 ServiceRuntime* service_runtime, | |
341 const SelLdrStartParams& params, | |
342 bool* success) { | |
343 if (pp_error != PP_OK) { | |
344 PLUGIN_PRINTF(("Plugin::StartSelLdrOnMainThread: non-PP_OK arg " | |
345 "-- SHOULD NOT HAPPEN\n")); | |
346 *success = false; | |
347 return; | |
348 } | |
349 *success = service_runtime->StartSelLdr(params); | |
350 // Signal outside of StartSelLdr here, so that the write to *success | |
351 // is done before signaling. | |
352 service_runtime->SignalStartSelLdrDone(); | |
353 } | |
354 | |
355 void Plugin::LoadNaClModule(nacl::DescWrapper* wrapper, | 341 void Plugin::LoadNaClModule(nacl::DescWrapper* wrapper, |
356 bool enable_dyncode_syscalls, | 342 bool enable_dyncode_syscalls, |
357 bool enable_exception_handling, | 343 bool enable_exception_handling, |
358 bool enable_crash_throttling, | 344 bool enable_crash_throttling, |
359 const pp::CompletionCallback& init_done_cb, | 345 const pp::CompletionCallback& init_done_cb, |
360 const pp::CompletionCallback& crash_cb) { | 346 const pp::CompletionCallback& crash_cb) { |
| 347 nacl::scoped_ptr<nacl::DescWrapper> scoped_wrapper(wrapper); |
| 348 pp::Core* core = pp::Module::Get()->core(); |
| 349 DCHECK(core->IsMainThread()); |
| 350 |
| 351 ErrorInfo error_info; |
361 // Before forking a new sel_ldr process, ensure that we do not leak | 352 // Before forking a new sel_ldr process, ensure that we do not leak |
362 // the ServiceRuntime object for an existing subprocess, and that any | 353 // the ServiceRuntime object for an existing subprocess, and that any |
363 // associated listener threads do not go unjoined because if they | 354 // associated listener threads do not go unjoined because if they |
364 // outlive the Plugin object, they will not be memory safe. | 355 // outlive the Plugin object, they will not be memory safe. |
365 ShutDownSubprocesses(); | 356 ShutDownSubprocesses(); |
366 SelLdrStartParams params(manifest_base_url(), | 357 SelLdrStartParams params(manifest_base_url(), |
367 true /* uses_irt */, | 358 true /* uses_irt */, |
368 true /* uses_ppapi */, | 359 true /* uses_ppapi */, |
369 enable_dev_interfaces_, | 360 enable_dev_interfaces_, |
370 enable_dyncode_syscalls, | 361 enable_dyncode_syscalls, |
371 enable_exception_handling, | 362 enable_exception_handling, |
372 enable_crash_throttling); | 363 enable_crash_throttling); |
373 if (LoadNaClModuleCommon(wrapper, &main_subprocess_, manifest_.get(), | 364 ServiceRuntime* service_runtime = |
374 true /* should_report_uma */, | 365 new ServiceRuntime(this, manifest_.get(), true, init_done_cb, crash_cb); |
375 params, init_done_cb, crash_cb)) { | 366 main_subprocess_.set_service_runtime(service_runtime); |
376 PLUGIN_PRINTF(("Plugin::LoadNaClModule (%s)\n", | 367 PLUGIN_PRINTF(("Plugin::LoadNaClModule (service_runtime=%p)\n", |
377 main_subprocess_.detailed_description().c_str())); | 368 static_cast<void*>(service_runtime))); |
| 369 if (NULL == service_runtime) { |
| 370 error_info.SetReport( |
| 371 ERROR_SEL_LDR_INIT, |
| 372 "sel_ldr init failure " + main_subprocess_.description()); |
| 373 ReportLoadError(error_info); |
| 374 return; |
| 375 } |
| 376 |
| 377 pp::CompletionCallback callback = callback_factory_.NewCallback( |
| 378 &Plugin::LoadNexeOnMainThread, |
| 379 service_runtime, scoped_wrapper.release(), crash_cb); |
| 380 StartSelLdrOnMainThread(PP_OK, service_runtime, params, |
| 381 callback.pp_completion_callback()); |
| 382 } |
| 383 |
| 384 void Plugin::LoadNexeOnMainThread(int32_t pp_error, |
| 385 ServiceRuntime* service_runtime, |
| 386 nacl::DescWrapper* wrapper, |
| 387 const pp::CompletionCallback& crash_cb) { |
| 388 nacl::scoped_ptr<nacl::DescWrapper> scoped_wrapper(wrapper); |
| 389 fprintf(stderr, "Plugin::LoadNexeOnMainThread\n"); |
| 390 ErrorInfo error_info; |
| 391 if (pp_error != PP_OK) { |
| 392 error_info.SetReport( |
| 393 ERROR_SEL_LDR_INIT, |
| 394 "sel_ldr start failure " + main_subprocess_.description()); |
| 395 ReportLoadError(error_info); |
| 396 return; |
| 397 } |
| 398 |
| 399 bool nexe_loaded = service_runtime->LoadNexeAndStart(wrapper, crash_cb); |
| 400 if (nexe_loaded) { |
| 401 PLUGIN_PRINTF(("Plugin::LoadNaClModule (nexe_loaded=%d)\n", nexe_loaded)); |
378 } | 402 } |
379 } | 403 } |
380 | 404 |
381 bool Plugin::LoadNaClModuleContinuationIntern(ErrorInfo* error_info) { | 405 bool Plugin::LoadNaClModuleContinuationIntern(ErrorInfo* error_info) { |
382 if (!main_subprocess_.StartSrpcServices()) { | 406 if (!main_subprocess_.StartSrpcServices()) { |
383 // The NaCl process probably crashed. On Linux, a crash causes this error, | 407 // The NaCl process probably crashed. On Linux, a crash causes this error, |
384 // while on other platforms, the error is detected below, when we attempt to | 408 // while on other platforms, the error is detected below, when we attempt to |
385 // start the proxy. Report a module initialization error here, to make it | 409 // start the proxy. Report a module initialization error here, to make it |
386 // less confusing for developers. | 410 // less confusing for developers. |
387 NaClLog(LOG_ERROR, "LoadNaClModuleContinuationIntern: " | 411 NaClLog(LOG_ERROR, "LoadNaClModuleContinuationIntern: " |
(...skipping 24 matching lines...) Expand all Loading... |
412 return false; | 436 return false; |
413 } | 437 } |
414 PLUGIN_PRINTF(("Plugin::LoadNaClModule (%s)\n", | 438 PLUGIN_PRINTF(("Plugin::LoadNaClModule (%s)\n", |
415 main_subprocess_.detailed_description().c_str())); | 439 main_subprocess_.detailed_description().c_str())); |
416 return true; | 440 return true; |
417 } | 441 } |
418 | 442 |
419 NaClSubprocess* Plugin::LoadHelperNaClModule(nacl::DescWrapper* wrapper, | 443 NaClSubprocess* Plugin::LoadHelperNaClModule(nacl::DescWrapper* wrapper, |
420 const Manifest* manifest, | 444 const Manifest* manifest, |
421 ErrorInfo* error_info) { | 445 ErrorInfo* error_info) { |
| 446 pp::Core* core = pp::Module::Get()->core(); |
| 447 DCHECK(!core->IsMainThread()); |
422 nacl::scoped_ptr<NaClSubprocess> nacl_subprocess( | 448 nacl::scoped_ptr<NaClSubprocess> nacl_subprocess( |
423 new NaClSubprocess("helper module", NULL, NULL)); | 449 new NaClSubprocess("helper module", NULL, NULL)); |
424 if (NULL == nacl_subprocess.get()) { | 450 if (NULL == nacl_subprocess.get()) { |
425 error_info->SetReport(ERROR_SEL_LDR_INIT, | 451 error_info->SetReport(ERROR_SEL_LDR_INIT, |
426 "unable to allocate helper subprocess."); | 452 "unable to allocate helper subprocess."); |
427 return NULL; | 453 return NULL; |
428 } | 454 } |
429 | 455 |
430 // Do not report UMA stats for translator-related nexes. | 456 // Do not report UMA stats for translator-related nexes. |
431 // TODO(sehr): define new UMA stats for translator related nexe events. | 457 // TODO(sehr): define new UMA stats for translator related nexe events. |
432 // NOTE: The PNaCl translator nexes are not built to use the IRT. This is | 458 // NOTE: The PNaCl translator nexes are not built to use the IRT. This is |
433 // done to save on address space and swap space. | 459 // done to save on address space and swap space. |
434 // TODO(jvoung): See if we still need the uses_ppapi variable, now that | 460 // TODO(jvoung): See if we still need the uses_ppapi variable, now that |
435 // LaunchSelLdr always happens on the main thread. | 461 // LaunchSelLdr always happens on the main thread. |
436 SelLdrStartParams params(manifest_base_url(), | 462 SelLdrStartParams params(manifest_base_url(), |
437 false /* uses_irt */, | 463 false /* uses_irt */, |
438 false /* uses_ppapi */, | 464 false /* uses_ppapi */, |
439 enable_dev_interfaces_, | 465 enable_dev_interfaces_, |
440 false /* enable_dyncode_syscalls */, | 466 false /* enable_dyncode_syscalls */, |
441 false /* enable_exception_handling */, | 467 false /* enable_exception_handling */, |
442 true /* enable_crash_throttling */); | 468 true /* enable_crash_throttling */); |
443 if (!LoadNaClModuleCommon(wrapper, nacl_subprocess.get(), manifest, | 469 if (!LoadNaClModuleFromBackgroundThread(wrapper, |
444 false /* should_report_uma */, | 470 nacl_subprocess.get(), |
445 params, | 471 manifest, |
446 pp::BlockUntilComplete(), | 472 params)) { |
447 pp::BlockUntilComplete())) { | |
448 return NULL; | 473 return NULL; |
449 } | 474 } |
450 // We need not wait for the init_done callback. We can block | 475 // We need not wait for the init_done callback. We can block |
451 // here in StartSrpcServices, since helper NaCl modules | 476 // here in StartSrpcServices, since helper NaCl modules |
452 // are spawned from a private thread. | 477 // are spawned from a private thread. |
453 // | 478 // |
454 // TODO(bsy): if helper module crashes, we should abort. | 479 // TODO(bsy): if helper module crashes, we should abort. |
455 // crash_cb is not used here, so we are relying on crashes | 480 // crash_cb is not used here, so we are relying on crashes |
456 // being detected in StartSrpcServices or later. | 481 // being detected in StartSrpcServices or later. |
457 // | 482 // |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
795 nexe_downloader_.url_to_open(), | 820 nexe_downloader_.url_to_open(), |
796 LENGTH_IS_COMPUTABLE, | 821 LENGTH_IS_COMPUTABLE, |
797 nexe_bytes_read, | 822 nexe_bytes_read, |
798 nexe_bytes_read); | 823 nexe_bytes_read); |
799 | 824 |
800 load_start_ = NaClGetTimeOfDayMicroseconds(); | 825 load_start_ = NaClGetTimeOfDayMicroseconds(); |
801 nacl::scoped_ptr<nacl::DescWrapper> | 826 nacl::scoped_ptr<nacl::DescWrapper> |
802 wrapper(wrapper_factory()->MakeFileDesc(file_desc_ok_to_close, O_RDONLY)); | 827 wrapper(wrapper_factory()->MakeFileDesc(file_desc_ok_to_close, O_RDONLY)); |
803 NaClLog(4, "NexeFileDidOpen: invoking LoadNaClModule\n"); | 828 NaClLog(4, "NexeFileDidOpen: invoking LoadNaClModule\n"); |
804 LoadNaClModule( | 829 LoadNaClModule( |
805 wrapper.get(), | 830 wrapper.release(), |
806 true, /* enable_dyncode_syscalls */ | 831 true, /* enable_dyncode_syscalls */ |
807 true, /* enable_exception_handling */ | 832 true, /* enable_exception_handling */ |
808 false, /* enable_crash_throttling */ | 833 false, /* enable_crash_throttling */ |
809 callback_factory_.NewCallback(&Plugin::NexeFileDidOpenContinuation), | 834 callback_factory_.NewCallback(&Plugin::NexeFileDidOpenContinuation), |
810 callback_factory_.NewCallback(&Plugin::NexeDidCrash)); | 835 callback_factory_.NewCallback(&Plugin::NexeDidCrash)); |
811 } | 836 } |
812 | 837 |
813 void Plugin::NexeFileDidOpenContinuation(int32_t pp_error) { | 838 void Plugin::NexeFileDidOpenContinuation(int32_t pp_error) { |
814 ErrorInfo error_info; | 839 ErrorInfo error_info; |
815 bool was_successful; | 840 bool was_successful; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
912 if (pp_error != PP_OK) { | 937 if (pp_error != PP_OK) { |
913 // Error should have been reported by pnacl. Just return. | 938 // Error should have been reported by pnacl. Just return. |
914 PLUGIN_PRINTF(("Plugin::BitcodeDidTranslate error in Pnacl\n")); | 939 PLUGIN_PRINTF(("Plugin::BitcodeDidTranslate error in Pnacl\n")); |
915 return; | 940 return; |
916 } | 941 } |
917 | 942 |
918 // Inform JavaScript that we successfully translated the bitcode to a nexe. | 943 // Inform JavaScript that we successfully translated the bitcode to a nexe. |
919 nacl::scoped_ptr<nacl::DescWrapper> | 944 nacl::scoped_ptr<nacl::DescWrapper> |
920 wrapper(pnacl_coordinator_.get()->ReleaseTranslatedFD()); | 945 wrapper(pnacl_coordinator_.get()->ReleaseTranslatedFD()); |
921 LoadNaClModule( | 946 LoadNaClModule( |
922 wrapper.get(), | 947 wrapper.release(), |
923 false, /* enable_dyncode_syscalls */ | 948 false, /* enable_dyncode_syscalls */ |
924 false, /* enable_exception_handling */ | 949 false, /* enable_exception_handling */ |
925 true, /* enable_crash_throttling */ | 950 true, /* enable_crash_throttling */ |
926 callback_factory_.NewCallback(&Plugin::BitcodeDidTranslateContinuation), | 951 callback_factory_.NewCallback(&Plugin::BitcodeDidTranslateContinuation), |
927 callback_factory_.NewCallback(&Plugin::NexeDidCrash)); | 952 callback_factory_.NewCallback(&Plugin::NexeDidCrash)); |
928 } | 953 } |
929 | 954 |
930 void Plugin::BitcodeDidTranslateContinuation(int32_t pp_error) { | 955 void Plugin::BitcodeDidTranslateContinuation(int32_t pp_error) { |
931 ErrorInfo error_info; | 956 ErrorInfo error_info; |
932 bool was_successful = LoadNaClModuleContinuationIntern(&error_info); | 957 bool was_successful = LoadNaClModuleContinuationIntern(&error_info); |
(...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1571 DCHECK(pp::Module::Get()->core()->IsMainThread()); | 1596 DCHECK(pp::Module::Get()->core()->IsMainThread()); |
1572 DCHECK(nacl_interface_); | 1597 DCHECK(nacl_interface_); |
1573 exit_status_ = exit_status; | 1598 exit_status_ = exit_status; |
1574 nacl_interface_->SetReadOnlyProperty(pp_instance(), | 1599 nacl_interface_->SetReadOnlyProperty(pp_instance(), |
1575 pp::Var("exitStatus").pp_var(), | 1600 pp::Var("exitStatus").pp_var(), |
1576 pp::Var(exit_status_).pp_var()); | 1601 pp::Var(exit_status_).pp_var()); |
1577 } | 1602 } |
1578 | 1603 |
1579 | 1604 |
1580 } // namespace plugin | 1605 } // namespace plugin |
OLD | NEW |