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 |
11 #include <string.h> | 11 #include <string.h> |
12 #include <string> | 12 #include <string> |
13 #include <utility> | 13 #include <utility> |
14 | 14 |
15 #include "base/compiler_specific.h" | 15 #include "base/compiler_specific.h" |
16 #include "components/nacl/renderer/plugin/plugin.h" | 16 #include "components/nacl/renderer/plugin/plugin.h" |
17 #include "components/nacl/renderer/plugin/plugin_error.h" | 17 #include "components/nacl/renderer/plugin/plugin_error.h" |
18 #include "components/nacl/renderer/plugin/pnacl_resources.h" | |
19 #include "components/nacl/renderer/plugin/sel_ldr_launcher_chrome.h" | 18 #include "components/nacl/renderer/plugin/sel_ldr_launcher_chrome.h" |
20 #include "components/nacl/renderer/plugin/srpc_client.h" | 19 #include "components/nacl/renderer/plugin/srpc_client.h" |
21 #include "components/nacl/renderer/plugin/utility.h" | 20 #include "components/nacl/renderer/plugin/utility.h" |
22 #include "native_client/src/include/nacl_macros.h" | 21 #include "native_client/src/include/nacl_macros.h" |
23 #include "native_client/src/include/nacl_scoped_ptr.h" | 22 #include "native_client/src/include/nacl_scoped_ptr.h" |
24 #include "native_client/src/include/portability_io.h" | 23 #include "native_client/src/include/portability_io.h" |
25 #include "native_client/src/include/portability_string.h" | 24 #include "native_client/src/include/portability_string.h" |
26 #include "native_client/src/public/imc_types.h" | 25 #include "native_client/src/public/imc_types.h" |
27 #include "native_client/src/shared/platform/nacl_check.h" | 26 #include "native_client/src/shared/platform/nacl_check.h" |
28 #include "native_client/src/shared/platform/nacl_log.h" | 27 #include "native_client/src/shared/platform/nacl_log.h" |
29 #include "native_client/src/shared/platform/nacl_sync.h" | |
30 #include "native_client/src/shared/platform/nacl_sync_checked.h" | |
31 #include "native_client/src/shared/platform/nacl_sync_raii.h" | |
32 #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h" | 28 #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h" |
33 #include "native_client/src/trusted/service_runtime/nacl_error_code.h" | 29 #include "native_client/src/trusted/service_runtime/nacl_error_code.h" |
34 #include "ppapi/c/pp_errors.h" | 30 #include "ppapi/c/pp_errors.h" |
35 #include "ppapi/cpp/completion_callback.h" | 31 #include "ppapi/cpp/completion_callback.h" |
36 #include "ppapi/cpp/core.h" | 32 #include "ppapi/cpp/core.h" |
37 | 33 |
38 namespace plugin { | 34 namespace plugin { |
39 | 35 |
40 ServiceRuntime::ServiceRuntime(Plugin* plugin, | 36 ServiceRuntime::ServiceRuntime(Plugin* plugin, |
41 PP_Instance pp_instance, | 37 PP_Instance pp_instance, |
42 bool main_service_runtime, | 38 bool main_service_runtime, |
43 bool uses_nonsfi_mode) | 39 bool uses_nonsfi_mode) |
44 : plugin_(plugin), | 40 : plugin_(plugin), |
45 pp_instance_(pp_instance), | 41 pp_instance_(pp_instance), |
46 main_service_runtime_(main_service_runtime), | 42 main_service_runtime_(main_service_runtime), |
47 uses_nonsfi_mode_(uses_nonsfi_mode), | 43 uses_nonsfi_mode_(uses_nonsfi_mode), |
48 start_sel_ldr_done_(false), | |
49 sel_ldr_wait_timed_out_(false), | |
50 start_nexe_done_(false), | |
51 nexe_started_ok_(false), | |
52 bootstrap_channel_(NACL_INVALID_HANDLE) { | 44 bootstrap_channel_(NACL_INVALID_HANDLE) { |
53 NaClSrpcChannelInitialize(&command_channel_); | 45 NaClSrpcChannelInitialize(&command_channel_); |
54 NaClXMutexCtor(&mu_); | |
55 NaClXCondVarCtor(&cond_); | |
56 } | 46 } |
57 | 47 |
58 bool ServiceRuntime::SetupCommandChannel() { | 48 bool ServiceRuntime::SetupCommandChannel() { |
59 NaClLog(4, "ServiceRuntime::SetupCommand (this=%p, subprocess=%p)\n", | 49 NaClLog(4, "ServiceRuntime::SetupCommand (this=%p, subprocess=%p)\n", |
60 static_cast<void*>(this), | 50 static_cast<void*>(this), |
61 static_cast<void*>(subprocess_.get())); | 51 static_cast<void*>(subprocess_.get())); |
62 // Set up the bootstrap channel in our subprocess so that we can establish | 52 // Set up the bootstrap channel in our subprocess so that we can establish |
63 // SRPC. | 53 // SRPC. |
64 subprocess_->set_channel(bootstrap_channel_); | 54 subprocess_->set_channel(bootstrap_channel_); |
65 | 55 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 PP_FromBool(main_service_runtime_), | 90 PP_FromBool(main_service_runtime_), |
101 params.url.c_str(), | 91 params.url.c_str(), |
102 ¶ms.file_info, | 92 ¶ms.file_info, |
103 PP_FromBool(uses_nonsfi_mode_), | 93 PP_FromBool(uses_nonsfi_mode_), |
104 params.process_type, | 94 params.process_type, |
105 &bootstrap_channel_, | 95 &bootstrap_channel_, |
106 callback.pp_completion_callback()); | 96 callback.pp_completion_callback()); |
107 subprocess_.reset(tmp_subprocess.release()); | 97 subprocess_.reset(tmp_subprocess.release()); |
108 } | 98 } |
109 | 99 |
110 bool ServiceRuntime::WaitForSelLdrStart() { | |
111 // Time to wait on condvar (for browser to create a new sel_ldr process on | |
112 // our behalf). Use 6 seconds to be *fairly* conservative. | |
113 // | |
114 // On surfaway, the CallOnMainThread above may never get scheduled | |
115 // to unblock this condvar, or the IPC reply from the browser to renderer | |
116 // might get canceled/dropped. However, it is currently important to | |
117 // avoid waiting indefinitely because ~PnaclCoordinator will attempt to | |
118 // join() the PnaclTranslateThread, and the PnaclTranslateThread is waiting | |
119 // for the signal before exiting. | |
120 static int64_t const kWaitTimeMicrosecs = 6 * NACL_MICROS_PER_UNIT; | |
121 int64_t left_to_wait = kWaitTimeMicrosecs; | |
122 int64_t deadline = NaClGetTimeOfDayMicroseconds() + left_to_wait; | |
123 nacl::MutexLocker take(&mu_); | |
124 while(!start_sel_ldr_done_ && left_to_wait > 0) { | |
125 struct nacl_abi_timespec left_timespec; | |
126 left_timespec.tv_sec = left_to_wait / NACL_MICROS_PER_UNIT; | |
127 left_timespec.tv_nsec = | |
128 (left_to_wait % NACL_MICROS_PER_UNIT) * NACL_NANOS_PER_MICRO; | |
129 NaClXCondVarTimedWaitRelative(&cond_, &mu_, &left_timespec); | |
130 int64_t now = NaClGetTimeOfDayMicroseconds(); | |
131 left_to_wait = deadline - now; | |
132 } | |
133 if (left_to_wait <= 0) | |
134 sel_ldr_wait_timed_out_ = true; | |
135 return start_sel_ldr_done_; | |
136 } | |
137 | |
138 void ServiceRuntime::SignalStartSelLdrDone() { | |
139 nacl::MutexLocker take(&mu_); | |
140 start_sel_ldr_done_ = true; | |
141 NaClXCondVarSignal(&cond_); | |
142 } | |
143 | |
144 bool ServiceRuntime::SelLdrWaitTimedOut() { | |
145 nacl::MutexLocker take(&mu_); | |
146 return sel_ldr_wait_timed_out_; | |
147 } | |
148 | |
149 bool ServiceRuntime::WaitForNexeStart() { | |
150 nacl::MutexLocker take(&mu_); | |
151 while (!start_nexe_done_) | |
152 NaClXCondVarWait(&cond_, &mu_); | |
153 return nexe_started_ok_; | |
154 } | |
155 | |
156 void ServiceRuntime::SignalNexeStarted(bool ok) { | |
157 nacl::MutexLocker take(&mu_); | |
158 start_nexe_done_ = true; | |
159 nexe_started_ok_ = ok; | |
160 NaClXCondVarSignal(&cond_); | |
161 } | |
162 | |
163 void ServiceRuntime::StartNexe() { | 100 void ServiceRuntime::StartNexe() { |
164 bool ok = SetupCommandChannel(); | 101 bool ok = SetupCommandChannel(); |
165 if (ok) { | 102 if (ok) { |
166 NaClLog(4, "ServiceRuntime::StartNexe (success)\n"); | 103 NaClLog(4, "ServiceRuntime::StartNexe (success)\n"); |
167 } | 104 } |
168 // This only matters if a background thread is waiting, but we signal in all | |
169 // cases to simplify the code. | |
170 SignalNexeStarted(ok); | |
171 } | 105 } |
172 | 106 |
173 void ServiceRuntime::ReportLoadError(const ErrorInfo& error_info) { | 107 void ServiceRuntime::ReportLoadError(const ErrorInfo& error_info) { |
174 if (main_service_runtime_) { | 108 if (main_service_runtime_) { |
175 plugin_->ReportLoadError(error_info); | 109 plugin_->ReportLoadError(error_info); |
176 } | 110 } |
177 } | 111 } |
178 | 112 |
179 SrpcClient* ServiceRuntime::SetupAppChannel() { | 113 SrpcClient* ServiceRuntime::SetupAppChannel() { |
180 NaClLog(4, "ServiceRuntime::SetupAppChannel (subprocess_=%p)\n", | 114 NaClLog(4, "ServiceRuntime::SetupAppChannel (subprocess_=%p)\n", |
181 reinterpret_cast<void*>(subprocess_.get())); | 115 reinterpret_cast<void*>(subprocess_.get())); |
182 nacl::DescWrapper* connect_desc = subprocess_->socket_addr()->Connect(); | 116 nacl::DescWrapper* connect_desc = subprocess_->socket_addr()->Connect(); |
183 if (NULL == connect_desc) { | 117 if (NULL == connect_desc) { |
184 NaClLog(LOG_ERROR, "ServiceRuntime::SetupAppChannel (connect failed)\n"); | 118 NaClLog(LOG_ERROR, "ServiceRuntime::SetupAppChannel (connect failed)\n"); |
185 return NULL; | 119 return NULL; |
186 } else { | 120 } else { |
187 NaClLog(4, "ServiceRuntime::SetupAppChannel (conect_desc=%p)\n", | 121 NaClLog(4, "ServiceRuntime::SetupAppChannel (connect_desc=%p)\n", |
188 static_cast<void*>(connect_desc)); | 122 static_cast<void*>(connect_desc)); |
189 SrpcClient* srpc_client = SrpcClient::New(connect_desc); | 123 SrpcClient* srpc_client = SrpcClient::New(connect_desc); |
190 NaClLog(4, "ServiceRuntime::SetupAppChannel (srpc_client=%p)\n", | 124 NaClLog(4, "ServiceRuntime::SetupAppChannel (srpc_client=%p)\n", |
191 static_cast<void*>(srpc_client)); | 125 static_cast<void*>(srpc_client)); |
192 delete connect_desc; | 126 delete connect_desc; |
193 return srpc_client; | 127 return srpc_client; |
194 } | 128 } |
195 } | 129 } |
196 | 130 |
197 void ServiceRuntime::Shutdown() { | 131 void ServiceRuntime::Shutdown() { |
198 // Abandon callbacks, tell service threads to quit if they were | 132 // Abandon callbacks, tell service threads to quit if they were |
199 // blocked waiting for main thread operations to finish. Note that | 133 // blocked waiting for main thread operations to finish. Note that |
200 // some callbacks must still await their completion event, e.g., | 134 // some callbacks must still await their completion event, e.g., |
201 // CallOnMainThread must still wait for the time out, or I/O events | 135 // CallOnMainThread must still wait for the time out, or I/O events |
202 // must finish, so resources associated with pending events cannot | 136 // must finish, so resources associated with pending events cannot |
203 // be deallocated. | 137 // be deallocated. |
204 | 138 |
205 // Note that this does waitpid() to get rid of any zombie subprocess. | 139 // Note that this does waitpid() to get rid of any zombie subprocess. |
206 subprocess_.reset(NULL); | 140 subprocess_.reset(NULL); |
207 | 141 |
208 NaClSrpcDtor(&command_channel_); | 142 NaClSrpcDtor(&command_channel_); |
209 } | 143 } |
210 | 144 |
211 ServiceRuntime::~ServiceRuntime() { | 145 ServiceRuntime::~ServiceRuntime() { |
212 NaClLog(4, "ServiceRuntime::~ServiceRuntime (this=%p)\n", | 146 NaClLog(4, "ServiceRuntime::~ServiceRuntime (this=%p)\n", |
213 static_cast<void*>(this)); | 147 static_cast<void*>(this)); |
214 // We do this just in case Shutdown() was not called. | 148 // We do this just in case Shutdown() was not called. |
215 subprocess_.reset(NULL); | 149 subprocess_.reset(NULL); |
216 | |
217 NaClCondVarDtor(&cond_); | |
218 NaClMutexDtor(&mu_); | |
219 } | 150 } |
220 | 151 |
221 } // namespace plugin | 152 } // namespace plugin |
OLD | NEW |