| 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 |