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 |