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 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 | 503 |
528 void Plugin::SetExitStatusOnMainThread(int32_t pp_error, | 504 void Plugin::SetExitStatusOnMainThread(int32_t pp_error, |
529 int exit_status) { | 505 int exit_status) { |
530 DCHECK(pp::Module::Get()->core()->IsMainThread()); | 506 DCHECK(pp::Module::Get()->core()->IsMainThread()); |
531 DCHECK(nacl_interface_); | 507 DCHECK(nacl_interface_); |
532 nacl_interface_->SetExitStatus(pp_instance(), exit_status); | 508 nacl_interface_->SetExitStatus(pp_instance(), exit_status); |
533 } | 509 } |
534 | 510 |
535 | 511 |
536 } // namespace plugin | 512 } // namespace plugin |
OLD | NEW |