| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 * Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 #define NACL_LOG_MODULE_NAME "Plugin_ServiceRuntime" | 7 #define NACL_LOG_MODULE_NAME "Plugin_ServiceRuntime" |
| 8 | 8 |
| 9 #include "components/nacl/renderer/plugin/service_runtime.h" | 9 #include "components/nacl/renderer/plugin/service_runtime.h" |
| 10 | 10 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 bool ServiceRuntime::StartModule() { | 81 bool ServiceRuntime::StartModule() { |
| 82 // start the module. otherwise we cannot connect for multimedia | 82 // start the module. otherwise we cannot connect for multimedia |
| 83 // subsystem since that is handled by user-level code (not secure!) | 83 // subsystem since that is handled by user-level code (not secure!) |
| 84 // in libsrpc. | 84 // in libsrpc. |
| 85 int load_status = -1; | 85 int load_status = -1; |
| 86 if (uses_nonsfi_mode_) { | 86 if (uses_nonsfi_mode_) { |
| 87 // In non-SFI mode, we don't need to call start_module SRPC to launch | 87 // In non-SFI mode, we don't need to call start_module SRPC to launch |
| 88 // the plugin. | 88 // the plugin. |
| 89 load_status = LOAD_OK; | 89 load_status = LOAD_OK; |
| 90 } else { | 90 } else { |
| 91 // We invoke start_module to unblock NaClWaitForStartModuleCommand in |
| 92 // sel_main_chrome, but the load_status is obtained by a different hook. |
| 93 // Remove this once NaClWaitForStartModuleCommand is no longer needed. |
| 91 NaClSrpcResultCodes rpc_result = | 94 NaClSrpcResultCodes rpc_result = |
| 92 NaClSrpcInvokeBySignature(&command_channel_, | 95 NaClSrpcInvokeBySignature(&command_channel_, |
| 93 "start_module::i", | 96 "start_module::i", |
| 94 &load_status); | 97 &load_status); |
| 95 | 98 |
| 96 if (NACL_SRPC_RESULT_OK != rpc_result) { | 99 if (NACL_SRPC_RESULT_OK != rpc_result) { |
| 97 ErrorInfo error_info; | 100 ErrorInfo error_info; |
| 98 error_info.SetReport(PP_NACL_ERROR_SEL_LDR_START_MODULE, | 101 error_info.SetReport(PP_NACL_ERROR_SEL_LDR_START_MODULE, |
| 99 "ServiceRuntime: could not start nacl module"); | 102 "ServiceRuntime: could not start nacl module"); |
| 100 ReportLoadError(error_info); | 103 ReportLoadError(error_info); |
| 101 return false; | 104 return false; |
| 102 } | 105 } |
| 103 } | 106 } |
| 104 | 107 |
| 105 NaClLog(4, "ServiceRuntime::StartModule (load_status=%d)\n", load_status); | 108 NaClLog(4, "ServiceRuntime::StartModule (load_status=%d)\n", load_status); |
| 106 if (main_service_runtime_) { | 109 return LOAD_OK == load_status; |
| 107 if (load_status < 0 || load_status > NACL_ERROR_CODE_MAX) | |
| 108 load_status = LOAD_STATUS_UNKNOWN; | |
| 109 GetNaClInterface()->ReportSelLdrStatus(pp_instance_, | |
| 110 load_status, | |
| 111 NACL_ERROR_CODE_MAX); | |
| 112 } | |
| 113 | |
| 114 if (LOAD_OK != load_status) { | |
| 115 ErrorInfo error_info; | |
| 116 error_info.SetReport( | |
| 117 PP_NACL_ERROR_SEL_LDR_START_STATUS, | |
| 118 NaClErrorString(static_cast<NaClErrorCode>(load_status))); | |
| 119 ReportLoadError(error_info); | |
| 120 return false; | |
| 121 } | |
| 122 return true; | |
| 123 } | 110 } |
| 124 | 111 |
| 125 void ServiceRuntime::StartSelLdr(const SelLdrStartParams& params, | 112 void ServiceRuntime::StartSelLdr(const SelLdrStartParams& params, |
| 126 pp::CompletionCallback callback) { | 113 pp::CompletionCallback callback) { |
| 127 NaClLog(4, "ServiceRuntime::Start\n"); | 114 NaClLog(4, "ServiceRuntime::Start\n"); |
| 128 | 115 |
| 129 nacl::scoped_ptr<SelLdrLauncherChrome> | 116 nacl::scoped_ptr<SelLdrLauncherChrome> |
| 130 tmp_subprocess(new SelLdrLauncherChrome()); | 117 tmp_subprocess(new SelLdrLauncherChrome()); |
| 131 if (NULL == tmp_subprocess.get()) { | 118 if (NULL == tmp_subprocess.get()) { |
| 132 NaClLog(LOG_ERROR, "ServiceRuntime::Start (subprocess create failed)\n"); | 119 NaClLog(LOG_ERROR, "ServiceRuntime::Start (subprocess create failed)\n"); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 nacl::MutexLocker take(&mu_); | 188 nacl::MutexLocker take(&mu_); |
| 202 start_nexe_done_ = true; | 189 start_nexe_done_ = true; |
| 203 nexe_started_ok_ = ok; | 190 nexe_started_ok_ = ok; |
| 204 NaClXCondVarSignal(&cond_); | 191 NaClXCondVarSignal(&cond_); |
| 205 } | 192 } |
| 206 | 193 |
| 207 void ServiceRuntime::StartNexe() { | 194 void ServiceRuntime::StartNexe() { |
| 208 bool ok = StartNexeInternal(); | 195 bool ok = StartNexeInternal(); |
| 209 if (ok) { | 196 if (ok) { |
| 210 NaClLog(4, "ServiceRuntime::StartNexe (success)\n"); | 197 NaClLog(4, "ServiceRuntime::StartNexe (success)\n"); |
| 211 } else { | |
| 212 ReapLogs(); | |
| 213 } | 198 } |
| 214 // This only matters if a background thread is waiting, but we signal in all | 199 // This only matters if a background thread is waiting, but we signal in all |
| 215 // cases to simplify the code. | 200 // cases to simplify the code. |
| 216 SignalNexeStarted(ok); | 201 SignalNexeStarted(ok); |
| 217 } | 202 } |
| 218 | 203 |
| 219 bool ServiceRuntime::StartNexeInternal() { | 204 bool ServiceRuntime::StartNexeInternal() { |
| 220 if (!SetupCommandChannel()) | 205 if (!SetupCommandChannel()) |
| 221 return false; | 206 return false; |
| 222 return StartModule(); | 207 return StartModule(); |
| 223 } | 208 } |
| 224 | 209 |
| 225 void ServiceRuntime::ReapLogs() { | |
| 226 // TODO(teravest): We should allow the NaCl process to crash itself when a | |
| 227 // module fails to start, and remove the call to RemoteLog() here. The | |
| 228 // reverse channel is no longer needed for crash reporting. | |
| 229 // | |
| 230 // The reasoning behind the current code behavior follows: | |
| 231 // On a load failure the NaCl process does not crash itself to | |
| 232 // avoid a race where the no-more-senders error on the reverse | |
| 233 // channel service thread might cause the crash-detection logic to | |
| 234 // kick in before the start_module RPC reply has been received. So | |
| 235 // we induce a NaCl process crash here. | |
| 236 RemoteLog(LOG_FATAL, "reap logs\n"); | |
| 237 | |
| 238 // TODO(teravest): Release subprocess_ here since it's no longer needed. It | |
| 239 // was previously kept around to collect crash log output from the bootstrap | |
| 240 // channel. | |
| 241 } | |
| 242 | |
| 243 void ServiceRuntime::ReportLoadError(const ErrorInfo& error_info) { | 210 void ServiceRuntime::ReportLoadError(const ErrorInfo& error_info) { |
| 244 if (main_service_runtime_) { | 211 if (main_service_runtime_) { |
| 245 plugin_->ReportLoadError(error_info); | 212 plugin_->ReportLoadError(error_info); |
| 246 } | 213 } |
| 247 } | 214 } |
| 248 | 215 |
| 249 SrpcClient* ServiceRuntime::SetupAppChannel() { | 216 SrpcClient* ServiceRuntime::SetupAppChannel() { |
| 250 NaClLog(4, "ServiceRuntime::SetupAppChannel (subprocess_=%p)\n", | 217 NaClLog(4, "ServiceRuntime::SetupAppChannel (subprocess_=%p)\n", |
| 251 reinterpret_cast<void*>(subprocess_.get())); | 218 reinterpret_cast<void*>(subprocess_.get())); |
| 252 nacl::DescWrapper* connect_desc = subprocess_->socket_addr()->Connect(); | 219 nacl::DescWrapper* connect_desc = subprocess_->socket_addr()->Connect(); |
| 253 if (NULL == connect_desc) { | 220 if (NULL == connect_desc) { |
| 254 NaClLog(LOG_ERROR, "ServiceRuntime::SetupAppChannel (connect failed)\n"); | 221 NaClLog(LOG_ERROR, "ServiceRuntime::SetupAppChannel (connect failed)\n"); |
| 255 return NULL; | 222 return NULL; |
| 256 } else { | 223 } else { |
| 257 NaClLog(4, "ServiceRuntime::SetupAppChannel (conect_desc=%p)\n", | 224 NaClLog(4, "ServiceRuntime::SetupAppChannel (conect_desc=%p)\n", |
| 258 static_cast<void*>(connect_desc)); | 225 static_cast<void*>(connect_desc)); |
| 259 SrpcClient* srpc_client = SrpcClient::New(connect_desc); | 226 SrpcClient* srpc_client = SrpcClient::New(connect_desc); |
| 260 NaClLog(4, "ServiceRuntime::SetupAppChannel (srpc_client=%p)\n", | 227 NaClLog(4, "ServiceRuntime::SetupAppChannel (srpc_client=%p)\n", |
| 261 static_cast<void*>(srpc_client)); | 228 static_cast<void*>(srpc_client)); |
| 262 delete connect_desc; | 229 delete connect_desc; |
| 263 return srpc_client; | 230 return srpc_client; |
| 264 } | 231 } |
| 265 } | 232 } |
| 266 | 233 |
| 267 bool ServiceRuntime::RemoteLog(int severity, const std::string& msg) { | |
| 268 NaClSrpcResultCodes rpc_result = | |
| 269 NaClSrpcInvokeBySignature(&command_channel_, | |
| 270 "log:is:", | |
| 271 severity, | |
| 272 strdup(msg.c_str())); | |
| 273 return (NACL_SRPC_RESULT_OK == rpc_result); | |
| 274 } | |
| 275 | |
| 276 void ServiceRuntime::Shutdown() { | 234 void ServiceRuntime::Shutdown() { |
| 277 // Abandon callbacks, tell service threads to quit if they were | 235 // Abandon callbacks, tell service threads to quit if they were |
| 278 // blocked waiting for main thread operations to finish. Note that | 236 // blocked waiting for main thread operations to finish. Note that |
| 279 // some callbacks must still await their completion event, e.g., | 237 // some callbacks must still await their completion event, e.g., |
| 280 // CallOnMainThread must still wait for the time out, or I/O events | 238 // CallOnMainThread must still wait for the time out, or I/O events |
| 281 // must finish, so resources associated with pending events cannot | 239 // must finish, so resources associated with pending events cannot |
| 282 // be deallocated. | 240 // be deallocated. |
| 283 | 241 |
| 284 // Note that this does waitpid() to get rid of any zombie subprocess. | 242 // Note that this does waitpid() to get rid of any zombie subprocess. |
| 285 subprocess_.reset(NULL); | 243 subprocess_.reset(NULL); |
| 286 | 244 |
| 287 NaClSrpcDtor(&command_channel_); | 245 NaClSrpcDtor(&command_channel_); |
| 288 } | 246 } |
| 289 | 247 |
| 290 ServiceRuntime::~ServiceRuntime() { | 248 ServiceRuntime::~ServiceRuntime() { |
| 291 NaClLog(4, "ServiceRuntime::~ServiceRuntime (this=%p)\n", | 249 NaClLog(4, "ServiceRuntime::~ServiceRuntime (this=%p)\n", |
| 292 static_cast<void*>(this)); | 250 static_cast<void*>(this)); |
| 293 // We do this just in case Shutdown() was not called. | 251 // We do this just in case Shutdown() was not called. |
| 294 subprocess_.reset(NULL); | 252 subprocess_.reset(NULL); |
| 295 | 253 |
| 296 NaClCondVarDtor(&cond_); | 254 NaClCondVarDtor(&cond_); |
| 297 NaClMutexDtor(&mu_); | 255 NaClMutexDtor(&mu_); |
| 298 } | 256 } |
| 299 | 257 |
| 300 } // namespace plugin | 258 } // namespace plugin |
| OLD | NEW |