| 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 "ppapi/native_client/src/trusted/plugin/service_runtime.h" | 9 #include "ppapi/native_client/src/trusted/plugin/service_runtime.h" |
| 10 | 10 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 #include "ppapi/native_client/src/trusted/plugin/plugin.h" | 44 #include "ppapi/native_client/src/trusted/plugin/plugin.h" |
| 45 #include "ppapi/native_client/src/trusted/plugin/plugin_error.h" | 45 #include "ppapi/native_client/src/trusted/plugin/plugin_error.h" |
| 46 #include "ppapi/native_client/src/trusted/plugin/pnacl_resources.h" | 46 #include "ppapi/native_client/src/trusted/plugin/pnacl_resources.h" |
| 47 #include "ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.h" | 47 #include "ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.h" |
| 48 #include "ppapi/native_client/src/trusted/plugin/srpc_client.h" | 48 #include "ppapi/native_client/src/trusted/plugin/srpc_client.h" |
| 49 #include "ppapi/native_client/src/trusted/plugin/utility.h" | 49 #include "ppapi/native_client/src/trusted/plugin/utility.h" |
| 50 #include "ppapi/native_client/src/trusted/weak_ref/call_on_main_thread.h" | 50 #include "ppapi/native_client/src/trusted/weak_ref/call_on_main_thread.h" |
| 51 | 51 |
| 52 namespace plugin { | 52 namespace plugin { |
| 53 | 53 |
| 54 OpenManifestEntryResource::~OpenManifestEntryResource() { | |
| 55 } | |
| 56 | |
| 57 PluginReverseInterface::PluginReverseInterface( | 54 PluginReverseInterface::PluginReverseInterface( |
| 58 nacl::WeakRefAnchor* anchor, | |
| 59 PP_Instance pp_instance, | 55 PP_Instance pp_instance, |
| 60 ServiceRuntime* service_runtime, | 56 ServiceRuntime* service_runtime, |
| 61 pp::CompletionCallback init_done_cb, | 57 pp::CompletionCallback init_done_cb, |
| 62 pp::CompletionCallback crash_cb) | 58 pp::CompletionCallback crash_cb) |
| 63 : anchor_(anchor), | 59 : pp_instance_(pp_instance), |
| 64 pp_instance_(pp_instance), | |
| 65 service_runtime_(service_runtime), | 60 service_runtime_(service_runtime), |
| 66 shutting_down_(false), | 61 shutting_down_(false), |
| 67 init_done_cb_(init_done_cb), | 62 init_done_cb_(init_done_cb), |
| 68 crash_cb_(crash_cb) { | 63 crash_cb_(crash_cb) { |
| 69 NaClXMutexCtor(&mu_); | 64 NaClXMutexCtor(&mu_); |
| 70 NaClXCondVarCtor(&cv_); | 65 NaClXCondVarCtor(&cv_); |
| 71 } | 66 } |
| 72 | 67 |
| 73 PluginReverseInterface::~PluginReverseInterface() { | 68 PluginReverseInterface::~PluginReverseInterface() { |
| 74 NaClCondVarDtor(&cv_); | 69 NaClCondVarDtor(&cv_); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 96 "PluginReverseInterface::StartupInitializationComplete:" | 91 "PluginReverseInterface::StartupInitializationComplete:" |
| 97 " invoking CB\n"); | 92 " invoking CB\n"); |
| 98 pp::Module::Get()->core()->CallOnMainThread(0, init_done_cb_, PP_OK); | 93 pp::Module::Get()->core()->CallOnMainThread(0, init_done_cb_, PP_OK); |
| 99 } else { | 94 } else { |
| 100 NaClLog(1, | 95 NaClLog(1, |
| 101 "PluginReverseInterface::StartupInitializationComplete:" | 96 "PluginReverseInterface::StartupInitializationComplete:" |
| 102 " init_done_cb_ not valid, skipping.\n"); | 97 " init_done_cb_ not valid, skipping.\n"); |
| 103 } | 98 } |
| 104 } | 99 } |
| 105 | 100 |
| 106 // TODO(bsy): OpenManifestEntry should use the manifest to ResolveKey | |
| 107 // and invoke StreamAsFile with a completion callback that invokes | |
| 108 // GetPOSIXFileDesc. | |
| 109 bool PluginReverseInterface::OpenManifestEntry(nacl::string url_key, | 101 bool PluginReverseInterface::OpenManifestEntry(nacl::string url_key, |
| 110 struct NaClFileInfo* info) { | 102 struct NaClFileInfo* info) { |
| 111 bool op_complete = false; // NB: mu_ and cv_ also controls access to this! | 103 // Not implemented. See ManifestServiceChannel for where this logic happens |
| 112 // The to_open object is owned by the weak ref callback. Because this function | 104 // now. |
| 113 // waits for the callback to finish, the to_open object will be deallocated on | 105 return false; |
| 114 // the main thread before this function can return. The pointers it contains | |
| 115 // to stack variables will not leak. | |
| 116 OpenManifestEntryResource* to_open = | |
| 117 new OpenManifestEntryResource(url_key, info, &op_complete); | |
| 118 CHECK(to_open != NULL); | |
| 119 NaClLog(4, "PluginReverseInterface::OpenManifestEntry: %s\n", | |
| 120 url_key.c_str()); | |
| 121 // This assumes we are not on the main thread. If false, we deadlock. | |
| 122 plugin::WeakRefCallOnMainThread( | |
| 123 anchor_, | |
| 124 0, | |
| 125 this, | |
| 126 &plugin::PluginReverseInterface::OpenManifestEntry_MainThreadContinuation, | |
| 127 to_open); | |
| 128 NaClLog(4, | |
| 129 "PluginReverseInterface::OpenManifestEntry:" | |
| 130 " waiting on main thread\n"); | |
| 131 | |
| 132 { | |
| 133 nacl::MutexLocker take(&mu_); | |
| 134 while (!shutting_down_ && !op_complete) | |
| 135 NaClXCondVarWait(&cv_, &mu_); | |
| 136 NaClLog(4, "PluginReverseInterface::OpenManifestEntry: done!\n"); | |
| 137 if (shutting_down_) { | |
| 138 NaClLog(4, | |
| 139 "PluginReverseInterface::OpenManifestEntry:" | |
| 140 " plugin is shutting down\n"); | |
| 141 return false; | |
| 142 } | |
| 143 } | |
| 144 | |
| 145 // info->desc has the returned descriptor if successful, else -1. | |
| 146 | |
| 147 // The caller is responsible for not closing info->desc. If it is | |
| 148 // closed prematurely, then another open could re-use the OS | |
| 149 // descriptor, confusing the opened_ map. If the caller is going to | |
| 150 // want to make a NaClDesc object and transfer it etc., then the | |
| 151 // caller should DUP the descriptor (but remember the original | |
| 152 // value) for use by the NaClDesc object, which closes when the | |
| 153 // object is destroyed. | |
| 154 NaClLog(4, | |
| 155 "PluginReverseInterface::OpenManifestEntry: info->desc = %d\n", | |
| 156 info->desc); | |
| 157 if (info->desc == -1) { | |
| 158 // TODO(bsy,ncbray): what else should we do with the error? This | |
| 159 // is a runtime error that may simply be a programming error in | |
| 160 // the untrusted code, or it may be something else wrong w/ the | |
| 161 // manifest. | |
| 162 NaClLog(4, "OpenManifestEntry: failed for key %s", url_key.c_str()); | |
| 163 } | |
| 164 return true; | |
| 165 } | |
| 166 | |
| 167 // Transfer point from OpenManifestEntry() which runs on the main thread | |
| 168 // (Some PPAPI actions -- like StreamAsFile -- can only run on the main thread). | |
| 169 // OpenManifestEntry() is waiting on a condvar for this continuation to | |
| 170 // complete. We Broadcast and awaken OpenManifestEntry() whenever we are done | |
| 171 // either here, or in a later MainThreadContinuation step, if there are | |
| 172 // multiple steps. | |
| 173 void PluginReverseInterface::OpenManifestEntry_MainThreadContinuation( | |
| 174 OpenManifestEntryResource* p, | |
| 175 int32_t err) { | |
| 176 UNREFERENCED_PARAMETER(err); | |
| 177 // CallOnMainThread continuations always called with err == PP_OK. | |
| 178 | |
| 179 NaClLog(4, "Entered OpenManifestEntry_MainThreadContinuation\n"); | |
| 180 | |
| 181 // Because p is owned by the callback of this invocation, so it is necessary | |
| 182 // to create another instance. | |
| 183 OpenManifestEntryResource* open_cont = new OpenManifestEntryResource(*p); | |
| 184 pp::CompletionCallback stream_cc = WeakRefNewCallback( | |
| 185 anchor_, | |
| 186 this, | |
| 187 &PluginReverseInterface::StreamAsFile_MainThreadContinuation, | |
| 188 open_cont); | |
| 189 | |
| 190 GetNaClInterface()->OpenManifestEntry( | |
| 191 pp_instance_, | |
| 192 PP_FromBool(!service_runtime_->main_service_runtime()), | |
| 193 p->url.c_str(), | |
| 194 &open_cont->pp_file_info, | |
| 195 stream_cc.pp_completion_callback()); | |
| 196 // p is deleted automatically. | |
| 197 } | |
| 198 | |
| 199 void PluginReverseInterface::StreamAsFile_MainThreadContinuation( | |
| 200 OpenManifestEntryResource* p, | |
| 201 int32_t result) { | |
| 202 NaClLog(4, "Entered StreamAsFile_MainThreadContinuation\n"); | |
| 203 { | |
| 204 nacl::MutexLocker take(&mu_); | |
| 205 if (result == PP_OK) { | |
| 206 // We downloaded this file to temporary storage for this plugin; it's | |
| 207 // reasonable to provide a file descriptor with write access. | |
| 208 p->file_info->desc = ConvertFileDescriptor(p->pp_file_info.handle, false); | |
| 209 p->file_info->file_token.lo = p->pp_file_info.token_lo; | |
| 210 p->file_info->file_token.hi = p->pp_file_info.token_hi; | |
| 211 NaClLog(4, | |
| 212 "StreamAsFile_MainThreadContinuation: PP_OK, desc %d\n", | |
| 213 p->file_info->desc); | |
| 214 } else { | |
| 215 NaClLog( | |
| 216 4, | |
| 217 "StreamAsFile_MainThreadContinuation: !PP_OK, setting desc -1\n"); | |
| 218 p->file_info->desc = -1; | |
| 219 } | |
| 220 *p->op_complete_ptr = true; | |
| 221 NaClXCondVarBroadcast(&cv_); | |
| 222 } | |
| 223 } | 106 } |
| 224 | 107 |
| 225 void PluginReverseInterface::ReportCrash() { | 108 void PluginReverseInterface::ReportCrash() { |
| 226 NaClLog(4, "PluginReverseInterface::ReportCrash\n"); | 109 NaClLog(4, "PluginReverseInterface::ReportCrash\n"); |
| 227 | 110 |
| 228 if (crash_cb_.pp_completion_callback().func != NULL) { | 111 if (crash_cb_.pp_completion_callback().func != NULL) { |
| 229 NaClLog(4, "PluginReverseInterface::ReportCrash: invoking CB\n"); | 112 NaClLog(4, "PluginReverseInterface::ReportCrash: invoking CB\n"); |
| 230 pp::Module::Get()->core()->CallOnMainThread(0, crash_cb_, PP_OK); | 113 pp::Module::Get()->core()->CallOnMainThread(0, crash_cb_, PP_OK); |
| 231 // Clear the callback to avoid it gets invoked twice. | 114 // Clear the callback to avoid it gets invoked twice. |
| 232 crash_cb_ = pp::CompletionCallback(); | 115 crash_cb_ = pp::CompletionCallback(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 250 PP_Instance pp_instance, | 133 PP_Instance pp_instance, |
| 251 bool main_service_runtime, | 134 bool main_service_runtime, |
| 252 bool uses_nonsfi_mode, | 135 bool uses_nonsfi_mode, |
| 253 pp::CompletionCallback init_done_cb, | 136 pp::CompletionCallback init_done_cb, |
| 254 pp::CompletionCallback crash_cb) | 137 pp::CompletionCallback crash_cb) |
| 255 : plugin_(plugin), | 138 : plugin_(plugin), |
| 256 pp_instance_(pp_instance), | 139 pp_instance_(pp_instance), |
| 257 main_service_runtime_(main_service_runtime), | 140 main_service_runtime_(main_service_runtime), |
| 258 uses_nonsfi_mode_(uses_nonsfi_mode), | 141 uses_nonsfi_mode_(uses_nonsfi_mode), |
| 259 reverse_service_(NULL), | 142 reverse_service_(NULL), |
| 260 anchor_(new nacl::WeakRefAnchor()), | 143 rev_interface_(new PluginReverseInterface(pp_instance, this, |
| 261 rev_interface_(new PluginReverseInterface(anchor_, pp_instance, this, | |
| 262 init_done_cb, crash_cb)), | 144 init_done_cb, crash_cb)), |
| 263 start_sel_ldr_done_(false), | 145 start_sel_ldr_done_(false), |
| 264 start_nexe_done_(false), | 146 start_nexe_done_(false), |
| 265 nexe_started_ok_(false), | 147 nexe_started_ok_(false), |
| 266 bootstrap_channel_(NACL_INVALID_HANDLE) { | 148 bootstrap_channel_(NACL_INVALID_HANDLE) { |
| 267 NaClSrpcChannelInitialize(&command_channel_); | 149 NaClSrpcChannelInitialize(&command_channel_); |
| 268 NaClXMutexCtor(&mu_); | 150 NaClXMutexCtor(&mu_); |
| 269 NaClXCondVarCtor(&cond_); | 151 NaClXCondVarCtor(&cond_); |
| 270 } | 152 } |
| 271 | 153 |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 576 NaClSrpcResultCodes rpc_result = | 458 NaClSrpcResultCodes rpc_result = |
| 577 NaClSrpcInvokeBySignature(&command_channel_, | 459 NaClSrpcInvokeBySignature(&command_channel_, |
| 578 "log:is:", | 460 "log:is:", |
| 579 severity, | 461 severity, |
| 580 strdup(msg.c_str())); | 462 strdup(msg.c_str())); |
| 581 return (NACL_SRPC_RESULT_OK == rpc_result); | 463 return (NACL_SRPC_RESULT_OK == rpc_result); |
| 582 } | 464 } |
| 583 | 465 |
| 584 void ServiceRuntime::Shutdown() { | 466 void ServiceRuntime::Shutdown() { |
| 585 rev_interface_->ShutDown(); | 467 rev_interface_->ShutDown(); |
| 586 anchor_->Abandon(); | |
| 587 // Abandon callbacks, tell service threads to quit if they were | 468 // Abandon callbacks, tell service threads to quit if they were |
| 588 // blocked waiting for main thread operations to finish. Note that | 469 // blocked waiting for main thread operations to finish. Note that |
| 589 // some callbacks must still await their completion event, e.g., | 470 // some callbacks must still await their completion event, e.g., |
| 590 // CallOnMainThread must still wait for the time out, or I/O events | 471 // CallOnMainThread must still wait for the time out, or I/O events |
| 591 // must finish, so resources associated with pending events cannot | 472 // must finish, so resources associated with pending events cannot |
| 592 // be deallocated. | 473 // be deallocated. |
| 593 | 474 |
| 594 // Note that this does waitpid() to get rid of any zombie subprocess. | 475 // Note that this does waitpid() to get rid of any zombie subprocess. |
| 595 subprocess_.reset(NULL); | 476 subprocess_.reset(NULL); |
| 596 | 477 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 610 | 491 |
| 611 ServiceRuntime::~ServiceRuntime() { | 492 ServiceRuntime::~ServiceRuntime() { |
| 612 NaClLog(4, "ServiceRuntime::~ServiceRuntime (this=%p)\n", | 493 NaClLog(4, "ServiceRuntime::~ServiceRuntime (this=%p)\n", |
| 613 static_cast<void*>(this)); | 494 static_cast<void*>(this)); |
| 614 // We do this just in case Shutdown() was not called. | 495 // We do this just in case Shutdown() was not called. |
| 615 subprocess_.reset(NULL); | 496 subprocess_.reset(NULL); |
| 616 if (reverse_service_ != NULL) | 497 if (reverse_service_ != NULL) |
| 617 reverse_service_->Unref(); | 498 reverse_service_->Unref(); |
| 618 | 499 |
| 619 rev_interface_->Unref(); | 500 rev_interface_->Unref(); |
| 620 | |
| 621 anchor_->Unref(); | |
| 622 NaClCondVarDtor(&cond_); | 501 NaClCondVarDtor(&cond_); |
| 623 NaClMutexDtor(&mu_); | 502 NaClMutexDtor(&mu_); |
| 624 } | 503 } |
| 625 | 504 |
| 626 void ServiceRuntime::set_exit_status(int exit_status) { | 505 void ServiceRuntime::set_exit_status(int exit_status) { |
| 627 nacl::MutexLocker take(&mu_); | 506 nacl::MutexLocker take(&mu_); |
| 628 if (main_service_runtime_) | 507 if (main_service_runtime_) |
| 629 plugin_->set_exit_status(exit_status & 0xff); | 508 plugin_->set_exit_status(exit_status & 0xff); |
| 630 } | 509 } |
| 631 | 510 |
| 632 nacl::string ServiceRuntime::GetCrashLogOutput() { | 511 nacl::string ServiceRuntime::GetCrashLogOutput() { |
| 633 if (NULL != subprocess_.get()) { | 512 if (NULL != subprocess_.get()) { |
| 634 return subprocess_->GetCrashLogOutput(); | 513 return subprocess_->GetCrashLogOutput(); |
| 635 } else { | 514 } else { |
| 636 return std::string(); | 515 return std::string(); |
| 637 } | 516 } |
| 638 } | 517 } |
| 639 | 518 |
| 640 } // namespace plugin | 519 } // namespace plugin |
| OLD | NEW |