| 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 "ppapi/native_client/src/trusted/plugin/plugin.h" | 5 #include "ppapi/native_client/src/trusted/plugin/plugin.h" |
| 6 | 6 |
| 7 #include <sys/stat.h> | 7 #include <sys/stat.h> |
| 8 #include <sys/types.h> | 8 #include <sys/types.h> |
| 9 | 9 |
| 10 #include <string> | 10 #include <string> |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 | 59 |
| 60 void Plugin::HistogramTimeSmall(const std::string& name, | 60 void Plugin::HistogramTimeSmall(const std::string& name, |
| 61 int64_t ms) { | 61 int64_t ms) { |
| 62 if (ms < 0) return; | 62 if (ms < 0) return; |
| 63 uma_interface_.HistogramCustomTimes(name, | 63 uma_interface_.HistogramCustomTimes(name, |
| 64 ms, | 64 ms, |
| 65 kTimeSmallMin, kTimeSmallMax, | 65 kTimeSmallMin, kTimeSmallMax, |
| 66 kTimeSmallBuckets); | 66 kTimeSmallBuckets); |
| 67 } | 67 } |
| 68 | 68 |
| 69 bool Plugin::LoadHelperNaClModule(PP_NaClFileInfo file_info, | 69 bool Plugin::LoadHelperNaClModuleInternal(NaClSubprocess* subprocess, |
| 70 NaClSubprocess* subprocess, | 70 const SelLdrStartParams& params) { |
| 71 const SelLdrStartParams& params) { | |
| 72 CHECK(!pp::Module::Get()->core()->IsMainThread()); | 71 CHECK(!pp::Module::Get()->core()->IsMainThread()); |
| 73 ServiceRuntime* service_runtime = | 72 ServiceRuntime* service_runtime = |
| 74 new ServiceRuntime(this, | 73 new ServiceRuntime(this, |
| 75 pp_instance(), | 74 pp_instance(), |
| 76 false, // No main_service_runtime. | 75 false, // No main_service_runtime. |
| 77 false, // No non-SFI mode (i.e. in SFI-mode). | 76 false, // No non-SFI mode (i.e. in SFI-mode). |
| 78 pp::BlockUntilComplete(), pp::BlockUntilComplete()); | 77 pp::BlockUntilComplete(), |
| 78 pp::BlockUntilComplete()); |
| 79 subprocess->set_service_runtime(service_runtime); | 79 subprocess->set_service_runtime(service_runtime); |
| 80 PLUGIN_PRINTF(("Plugin::LoadHelperNaClModule " | 80 PLUGIN_PRINTF(("Plugin::LoadHelperNaClModule " |
| 81 "(service_runtime=%p)\n", | 81 "(service_runtime=%p)\n", |
| 82 static_cast<void*>(service_runtime))); | 82 static_cast<void*>(service_runtime))); |
| 83 | 83 |
| 84 // Now start the SelLdr instance. This must be created on the main thread. | 84 // Now start the SelLdr instance. This must be created on the main thread. |
| 85 bool service_runtime_started = false; | 85 bool service_runtime_started = false; |
| 86 pp::CompletionCallback sel_ldr_callback = | 86 pp::CompletionCallback sel_ldr_callback = |
| 87 callback_factory_.NewCallback(&Plugin::SignalStartSelLdrDone, | 87 callback_factory_.NewCallback(&Plugin::SignalStartSelLdrDone, |
| 88 &service_runtime_started, | 88 &service_runtime_started, |
| 89 service_runtime); | 89 service_runtime); |
| 90 pp::CompletionCallback callback = | 90 pp::CompletionCallback callback = |
| 91 callback_factory_.NewCallback(&Plugin::StartSelLdrOnMainThread, | 91 callback_factory_.NewCallback(&Plugin::StartSelLdrOnMainThread, |
| 92 service_runtime, params, | 92 service_runtime, params, |
| 93 sel_ldr_callback); | 93 sel_ldr_callback); |
| 94 pp::Module::Get()->core()->CallOnMainThread(0, callback, 0); | 94 pp::Module::Get()->core()->CallOnMainThread(0, callback, 0); |
| 95 if (!service_runtime->WaitForSelLdrStart()) { | 95 if (!service_runtime->WaitForSelLdrStart()) { |
| 96 PLUGIN_PRINTF(("Plugin::LoadHelperNaClModule " | 96 PLUGIN_PRINTF(("Plugin::LoadHelperNaClModule " |
| 97 "WaitForSelLdrStart timed out!\n")); | 97 "WaitForSelLdrStart timed out!\n")); |
| 98 return false; | 98 return false; |
| 99 } | 99 } |
| 100 PLUGIN_PRINTF(("Plugin::LoadHelperNaClModule (service_runtime_started=%d)\n", | 100 PLUGIN_PRINTF(("Plugin::LoadHelperNaClModule (service_runtime_started=%d)\n", |
| 101 service_runtime_started)); | 101 service_runtime_started)); |
| 102 if (!service_runtime_started) | 102 if (!service_runtime_started) |
| 103 return false; | 103 return false; |
| 104 | 104 |
| 105 // Now actually load the nexe, which can happen on a background thread. | 105 // Now actually start the nexe. |
| 106 // | 106 // |
| 107 // We can't use pp::BlockUntilComplete() inside an in-process plugin, so we | 107 // We can't use pp::BlockUntilComplete() inside an in-process plugin, so we |
| 108 // have to roll our own blocking logic, similar to WaitForSelLdrStart() | 108 // have to roll our own blocking logic, similar to WaitForSelLdrStart() |
| 109 // above, except without timeout logic. | 109 // above, except without timeout logic. |
| 110 pp::Module::Get()->core()->CallOnMainThread( | 110 pp::Module::Get()->core()->CallOnMainThread( |
| 111 0, | 111 0, |
| 112 callback_factory_.NewCallback( | 112 callback_factory_.NewCallback(&Plugin::StartNexe, service_runtime)); |
| 113 &Plugin::LoadNexeAndStart, | |
| 114 service_runtime, | |
| 115 file_info)); | |
| 116 return service_runtime->WaitForNexeStart(); | 113 return service_runtime->WaitForNexeStart(); |
| 117 } | 114 } |
| 118 | 115 |
| 119 void Plugin::StartSelLdrOnMainThread(int32_t pp_error, | 116 void Plugin::StartSelLdrOnMainThread(int32_t pp_error, |
| 120 ServiceRuntime* service_runtime, | 117 ServiceRuntime* service_runtime, |
| 121 const SelLdrStartParams& params, | 118 const SelLdrStartParams& params, |
| 122 pp::CompletionCallback callback) { | 119 pp::CompletionCallback callback) { |
| 123 if (pp_error != PP_OK) { | 120 if (pp_error != PP_OK) { |
| 124 PLUGIN_PRINTF(("Plugin::StartSelLdrOnMainThread: non-PP_OK arg " | 121 PLUGIN_PRINTF(("Plugin::StartSelLdrOnMainThread: non-PP_OK arg " |
| 125 "-- SHOULD NOT HAPPEN\n")); | 122 "-- SHOULD NOT HAPPEN\n")); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 146 CHECK(pp::Module::Get()->core()->IsMainThread()); | 143 CHECK(pp::Module::Get()->core()->IsMainThread()); |
| 147 // Before forking a new sel_ldr process, ensure that we do not leak | 144 // Before forking a new sel_ldr process, ensure that we do not leak |
| 148 // the ServiceRuntime object for an existing subprocess, and that any | 145 // the ServiceRuntime object for an existing subprocess, and that any |
| 149 // associated listener threads do not go unjoined because if they | 146 // associated listener threads do not go unjoined because if they |
| 150 // outlive the Plugin object, they will not be memory safe. | 147 // outlive the Plugin object, they will not be memory safe. |
| 151 ShutDownSubprocesses(); | 148 ShutDownSubprocesses(); |
| 152 pp::Var manifest_base_url = | 149 pp::Var manifest_base_url = |
| 153 pp::Var(pp::PASS_REF, nacl_interface_->GetManifestBaseURL(pp_instance())); | 150 pp::Var(pp::PASS_REF, nacl_interface_->GetManifestBaseURL(pp_instance())); |
| 154 std::string manifest_base_url_str = manifest_base_url.AsString(); | 151 std::string manifest_base_url_str = manifest_base_url.AsString(); |
| 155 | 152 |
| 156 PP_NaClFileInfo file_info_for_srpc = kInvalidNaClFileInfo; | |
| 157 PP_NaClFileInfo file_info_for_ipc = kInvalidNaClFileInfo; | |
| 158 if (uses_nonsfi_mode) { | |
| 159 // In non-SFI mode, LaunchSelLdr is used to pass the nexe file's descriptor | |
| 160 // to the NaCl loader process. | |
| 161 file_info_for_ipc = file_info; | |
| 162 } else { | |
| 163 // Otherwise (i.e. in SFI-mode), LoadModule SRPC is still being used. | |
| 164 file_info_for_srpc = file_info; | |
| 165 } | |
| 166 | |
| 167 SelLdrStartParams params(manifest_base_url_str, | 153 SelLdrStartParams params(manifest_base_url_str, |
| 168 file_info_for_ipc, | 154 file_info, |
| 169 true /* uses_irt */, | 155 true /* uses_irt */, |
| 170 true /* uses_ppapi */, | 156 true /* uses_ppapi */, |
| 171 enable_dyncode_syscalls, | 157 enable_dyncode_syscalls, |
| 172 enable_exception_handling, | 158 enable_exception_handling, |
| 173 enable_crash_throttling); | 159 enable_crash_throttling); |
| 174 ErrorInfo error_info; | 160 ErrorInfo error_info; |
| 175 ServiceRuntime* service_runtime = new ServiceRuntime( | 161 ServiceRuntime* service_runtime = new ServiceRuntime( |
| 176 this, pp_instance(), true, uses_nonsfi_mode, init_done_cb, crash_cb); | 162 this, pp_instance(), true, uses_nonsfi_mode, init_done_cb, crash_cb); |
| 177 main_subprocess_.set_service_runtime(service_runtime); | 163 main_subprocess_.set_service_runtime(service_runtime); |
| 178 PLUGIN_PRINTF(("Plugin::LoadNaClModule (service_runtime=%p)\n", | 164 PLUGIN_PRINTF(("Plugin::LoadNaClModule (service_runtime=%p)\n", |
| 179 static_cast<void*>(service_runtime))); | 165 static_cast<void*>(service_runtime))); |
| 180 if (NULL == service_runtime) { | 166 if (NULL == service_runtime) { |
| 181 error_info.SetReport( | 167 error_info.SetReport( |
| 182 PP_NACL_ERROR_SEL_LDR_INIT, | 168 PP_NACL_ERROR_SEL_LDR_INIT, |
| 183 "sel_ldr init failure " + main_subprocess_.description()); | 169 "sel_ldr init failure " + main_subprocess_.description()); |
| 184 ReportLoadError(error_info); | 170 ReportLoadError(error_info); |
| 185 return; | 171 return; |
| 186 } | 172 } |
| 187 | 173 |
| 188 // We don't take any action once nexe loading has completed, so pass an empty | 174 // We don't take any action once nexe loading has completed, so pass an empty |
| 189 // callback here for |callback|. | 175 // callback here for |callback|. |
| 190 pp::CompletionCallback callback = callback_factory_.NewCallback( | 176 pp::CompletionCallback callback = callback_factory_.NewCallback( |
| 191 &Plugin::LoadNexeAndStart, service_runtime, file_info_for_srpc); | 177 &Plugin::StartNexe, service_runtime); |
| 192 StartSelLdrOnMainThread( | 178 StartSelLdrOnMainThread( |
| 193 static_cast<int32_t>(PP_OK), service_runtime, params, callback); | 179 static_cast<int32_t>(PP_OK), service_runtime, params, callback); |
| 194 } | 180 } |
| 195 | 181 |
| 196 void Plugin::LoadNexeAndStart(int32_t pp_error, | 182 void Plugin::StartNexe(int32_t pp_error, ServiceRuntime* service_runtime) { |
| 197 ServiceRuntime* service_runtime, | |
| 198 PP_NaClFileInfo file_info) { | |
| 199 CHECK(pp::Module::Get()->core()->IsMainThread()); | 183 CHECK(pp::Module::Get()->core()->IsMainThread()); |
| 200 if (pp_error != PP_OK) | 184 if (pp_error != PP_OK) |
| 201 return; | 185 return; |
| 202 service_runtime->LoadNexeAndStart(file_info); | 186 service_runtime->StartNexe(); |
| 203 } | 187 } |
| 204 | 188 |
| 205 bool Plugin::LoadNaClModuleContinuationIntern() { | 189 bool Plugin::LoadNaClModuleContinuationIntern() { |
| 206 ErrorInfo error_info; | 190 ErrorInfo error_info; |
| 207 if (!uses_nonsfi_mode_) { | 191 if (!uses_nonsfi_mode_) { |
| 208 if (!main_subprocess_.StartSrpcServices()) { | 192 if (!main_subprocess_.StartSrpcServices()) { |
| 209 // The NaCl process probably crashed. On Linux, a crash causes this | 193 // The NaCl process probably crashed. On Linux, a crash causes this |
| 210 // error, while on other platforms, the error is detected below, when we | 194 // error, while on other platforms, the error is detected below, when we |
| 211 // attempt to start the proxy. Report a module initialization error here, | 195 // attempt to start the proxy. Report a module initialization error here, |
| 212 // to make it less confusing for developers. | 196 // to make it less confusing for developers. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 235 if (NULL == nacl_subprocess.get()) { | 219 if (NULL == nacl_subprocess.get()) { |
| 236 error_info->SetReport(PP_NACL_ERROR_SEL_LDR_INIT, | 220 error_info->SetReport(PP_NACL_ERROR_SEL_LDR_INIT, |
| 237 "unable to allocate helper subprocess."); | 221 "unable to allocate helper subprocess."); |
| 238 return NULL; | 222 return NULL; |
| 239 } | 223 } |
| 240 | 224 |
| 241 // Do not report UMA stats for translator-related nexes. | 225 // Do not report UMA stats for translator-related nexes. |
| 242 // TODO(sehr): define new UMA stats for translator related nexe events. | 226 // TODO(sehr): define new UMA stats for translator related nexe events. |
| 243 // NOTE: The PNaCl translator nexes are not built to use the IRT. This is | 227 // NOTE: The PNaCl translator nexes are not built to use the IRT. This is |
| 244 // done to save on address space and swap space. | 228 // done to save on address space and swap space. |
| 245 // | |
| 246 // Currently, this works only in SFI-mode. So, LoadModule SRPC is still used. | |
| 247 // So, pass kInvalidNaClFileInfo here, and instead |file_info| is passed | |
| 248 // to LoadNaClModuleFromBackgroundThread() below. | |
| 249 // TODO(teravest, hidehiko): Pass file_info to params, so that LaunchSelLdr | |
| 250 // will look at the info. | |
| 251 SelLdrStartParams params(helper_url, | 229 SelLdrStartParams params(helper_url, |
| 252 kInvalidNaClFileInfo, | 230 file_info, |
| 253 false /* uses_irt */, | 231 false /* uses_irt */, |
| 254 false /* uses_ppapi */, | 232 false /* uses_ppapi */, |
| 255 false /* enable_dyncode_syscalls */, | 233 false /* enable_dyncode_syscalls */, |
| 256 false /* enable_exception_handling */, | 234 false /* enable_exception_handling */, |
| 257 true /* enable_crash_throttling */); | 235 true /* enable_crash_throttling */); |
| 258 | 236 |
| 259 // Helper NaCl modules always use the PNaCl manifest, as there is no | 237 // Helper NaCl modules always use the PNaCl manifest, as there is no |
| 260 // corresponding NMF. | 238 // corresponding NMF. |
| 261 if (!LoadHelperNaClModule(file_info, | 239 if (!LoadHelperNaClModuleInternal(nacl_subprocess.get(), params)) |
| 262 nacl_subprocess.get(), | |
| 263 params)) { | |
| 264 return NULL; | 240 return NULL; |
| 265 } | 241 |
| 266 // We need not wait for the init_done callback. We can block | 242 // We need not wait for the init_done callback. We can block |
| 267 // here in StartSrpcServices, since helper NaCl modules | 243 // here in StartSrpcServices, since helper NaCl modules |
| 268 // are spawned from a private thread. | 244 // are spawned from a private thread. |
| 269 // | 245 // |
| 270 // TODO(bsy): if helper module crashes, we should abort. | 246 // TODO(bsy): if helper module crashes, we should abort. |
| 271 // crash_cb is not used here, so we are relying on crashes | 247 // crash_cb is not used here, so we are relying on crashes |
| 272 // being detected in StartSrpcServices or later. | 248 // being detected in StartSrpcServices or later. |
| 273 // | 249 // |
| 274 // NB: More refactoring might be needed, however, if helper | 250 // NB: More refactoring might be needed, however, if helper |
| 275 // NaCl modules have their own manifest. Currently the | 251 // NaCl modules have their own manifest. Currently the |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 | 504 |
| 529 void Plugin::SetExitStatusOnMainThread(int32_t pp_error, | 505 void Plugin::SetExitStatusOnMainThread(int32_t pp_error, |
| 530 int exit_status) { | 506 int exit_status) { |
| 531 DCHECK(pp::Module::Get()->core()->IsMainThread()); | 507 DCHECK(pp::Module::Get()->core()->IsMainThread()); |
| 532 DCHECK(nacl_interface_); | 508 DCHECK(nacl_interface_); |
| 533 nacl_interface_->SetExitStatus(pp_instance(), exit_status); | 509 nacl_interface_->SetExitStatus(pp_instance(), exit_status); |
| 534 } | 510 } |
| 535 | 511 |
| 536 | 512 |
| 537 } // namespace plugin | 513 } // namespace plugin |
| OLD | NEW |