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 "native_client/src/trusted/plugin/pnacl_translate_thread.h" | 5 #include "native_client/src/trusted/plugin/pnacl_translate_thread.h" |
6 | 6 |
7 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" | 7 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" |
8 #include "native_client/src/trusted/plugin/plugin.h" | 8 #include "native_client/src/trusted/plugin/plugin.h" |
9 #include "native_client/src/trusted/plugin/pnacl_resources.h" | 9 #include "native_client/src/trusted/plugin/pnacl_resources.h" |
10 #include "native_client/src/trusted/plugin/srpc_params.h" | 10 #include "native_client/src/trusted/plugin/srpc_params.h" |
11 #include "native_client/src/trusted/plugin/temporary_file.h" | 11 #include "native_client/src/trusted/plugin/temporary_file.h" |
12 #include "native_client/src/trusted/plugin/utility.h" | 12 #include "native_client/src/trusted/plugin/utility.h" |
13 | 13 |
14 namespace plugin { | 14 namespace plugin { |
15 | 15 |
16 PnaclTranslateThread::PnaclTranslateThread() : subprocesses_should_die_(false), | 16 PnaclTranslateThread::PnaclTranslateThread() : done_(false), |
17 current_rev_interface_(NULL), | |
18 done_(false), | |
19 manifest_(NULL), | 17 manifest_(NULL), |
20 ld_manifest_(NULL), | 18 ld_manifest_(NULL), |
21 obj_file_(NULL), | 19 obj_file_(NULL), |
22 nexe_file_(NULL), | 20 nexe_file_(NULL), |
23 coordinator_error_info_(NULL), | 21 coordinator_error_info_(NULL), |
24 resources_(NULL), | 22 resources_(NULL), |
25 plugin_(NULL) { | 23 plugin_(NULL) { |
26 NaClXMutexCtor(&subprocess_mu_); | 24 NaClXMutexCtor(&subprocess_mu_); |
27 NaClXMutexCtor(&cond_mu_); | 25 NaClXMutexCtor(&cond_mu_); |
28 NaClXCondVarCtor(&buffer_cond_); | 26 NaClXCondVarCtor(&buffer_cond_); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
115 } | 113 } |
116 | 114 |
117 void WINAPI PnaclTranslateThread::DoTranslateThread(void* arg) { | 115 void WINAPI PnaclTranslateThread::DoTranslateThread(void* arg) { |
118 PnaclTranslateThread* translator = | 116 PnaclTranslateThread* translator = |
119 reinterpret_cast<PnaclTranslateThread*>(arg); | 117 reinterpret_cast<PnaclTranslateThread*>(arg); |
120 translator->DoTranslate(); | 118 translator->DoTranslate(); |
121 } | 119 } |
122 | 120 |
123 void PnaclTranslateThread::DoTranslate() { | 121 void PnaclTranslateThread::DoTranslate() { |
124 ErrorInfo error_info; | 122 ErrorInfo error_info; |
125 nacl::scoped_ptr<NaClSubprocess> llc_subprocess( | |
126 StartSubprocess(PnaclUrls::GetLlcUrl(), manifest_, &error_info)); | |
127 if (llc_subprocess == NULL) { | |
128 TranslateFailed("Compile process could not be created: " + | |
129 error_info.message()); | |
130 return; | |
131 } | |
132 // Run LLC. | |
133 SrpcParams params; | 123 SrpcParams params; |
134 nacl::DescWrapper* llc_out_file = obj_file_->get_wrapper(); | 124 nacl::DescWrapper* llc_out_file = obj_file_->get_wrapper(); |
135 PluginReverseInterface* llc_reverse = | |
136 llc_subprocess->service_runtime()->rev_interface(); | |
137 llc_reverse->AddTempQuotaManagedFile(obj_file_->identifier()); | |
138 RegisterReverseInterface(llc_reverse); | |
139 | 125 |
140 if (!llc_subprocess->InvokeSrpcMethod("StreamInit", | 126 { |
141 "h", | 127 nacl::MutexLocker ml(&subprocess_mu_); |
142 ¶ms, | 128 llc_subprocess_.reset( |
143 llc_out_file->desc())) { | 129 StartSubprocess(PnaclUrls::GetLlcUrl(), manifest_, &error_info)); |
144 // StreamInit returns an error message if the RPC fails. | 130 if (llc_subprocess_ == NULL) { |
145 TranslateFailed(nacl::string("Stream init failed: ") + | 131 TranslateFailed("Compile process could not be created: " + |
146 nacl::string(params.outs()[0]->arrays.str)); | 132 error_info.message()); |
133 return; | |
134 } | |
135 // Run LLC. | |
136 PluginReverseInterface* llc_reverse = | |
137 llc_subprocess_->service_runtime()->rev_interface(); | |
138 llc_reverse->AddTempQuotaManagedFile(obj_file_->identifier()); | |
139 } | |
140 | |
141 if (!llc_subprocess_->InvokeSrpcMethod("StreamInit", | |
142 "h", | |
143 ¶ms, | |
144 llc_out_file->desc())) { | |
145 if (llc_subprocess_->srpc_client()->GetLastError() == | |
146 NACL_SRPC_RESULT_APP_ERROR) { | |
147 // The error message is only present if the error was returned from llc | |
148 TranslateFailed(nacl::string("Stream init failed: ") + | |
149 nacl::string(params.outs()[0]->arrays.str)); | |
150 } else { | |
151 TranslateFailed("Stream init internal error"); | |
152 } | |
147 return; | 153 return; |
148 } | 154 } |
149 | 155 |
150 PLUGIN_PRINTF(("PnaclCoordinator: StreamInit successful\n")); | 156 PLUGIN_PRINTF(("PnaclCoordinator: StreamInit successful\n")); |
151 | 157 |
152 // llc process is started. | 158 // llc process is started. |
153 while(!done_ || data_buffers_.size() > 0) { | 159 while(!done_ || data_buffers_.size() > 0) { |
154 NaClXMutexLock(&cond_mu_); | 160 NaClXMutexLock(&cond_mu_); |
155 while(!done_ && data_buffers_.size() == 0) { | 161 while(!done_ && data_buffers_.size() == 0) { |
156 NaClXCondVarWait(&buffer_cond_, &cond_mu_); | 162 NaClXCondVarWait(&buffer_cond_, &cond_mu_); |
157 } | 163 } |
158 PLUGIN_PRINTF(("PnaclTranslateThread awake, done %d, size %d\n", | 164 PLUGIN_PRINTF(("PnaclTranslateThread awake, done %d, size %d\n", |
159 done_, data_buffers_.size())); | 165 done_, data_buffers_.size())); |
160 if (data_buffers_.size() > 0) { | 166 if (data_buffers_.size() > 0) { |
161 std::vector<char> data; | 167 std::vector<char> data; |
162 data.swap(data_buffers_.front()); | 168 data.swap(data_buffers_.front()); |
163 data_buffers_.pop_front(); | 169 data_buffers_.pop_front(); |
164 NaClXMutexUnlock(&cond_mu_); | 170 NaClXMutexUnlock(&cond_mu_); |
165 PLUGIN_PRINTF(("StreamChunk\n")); | 171 PLUGIN_PRINTF(("StreamChunk\n")); |
166 if (!llc_subprocess->InvokeSrpcMethod("StreamChunk", | 172 if (!llc_subprocess_->InvokeSrpcMethod("StreamChunk", |
167 "C", | 173 "C", |
168 ¶ms, | 174 ¶ms, |
169 &data[0], | 175 &data[0], |
170 data.size())) { | 176 data.size())) { |
171 TranslateFailed("Compile stream chunk failed."); | 177 TranslateFailed("Compile stream chunk failed."); |
172 return; | 178 return; |
173 } | 179 } |
174 PLUGIN_PRINTF(("StreamChunk Successful\n")); | 180 PLUGIN_PRINTF(("StreamChunk Successful\n")); |
175 } else { | 181 } else { |
176 NaClXMutexUnlock(&cond_mu_); | 182 NaClXMutexUnlock(&cond_mu_); |
177 } | 183 } |
178 if (SubprocessesShouldDie()) { | |
179 TranslateFailed("Stopped by coordinator."); | |
180 return; | |
181 } | |
182 } | 184 } |
183 PLUGIN_PRINTF(("PnaclTranslateThread done with chunks\n")); | 185 PLUGIN_PRINTF(("PnaclTranslateThread done with chunks\n")); |
184 // Finish llc. | 186 // Finish llc. |
185 if(!llc_subprocess->InvokeSrpcMethod("StreamEnd", | 187 if(!llc_subprocess_->InvokeSrpcMethod("StreamEnd", |
186 "", | 188 "", |
187 ¶ms)) { | 189 ¶ms)) { |
188 PLUGIN_PRINTF(("PnaclTranslateThread StreamEnd failed\n")); | 190 PLUGIN_PRINTF(("PnaclTranslateThread StreamEnd failed\n")); |
189 TranslateFailed(params.outs()[3]->arrays.str); | 191 if (llc_subprocess_->srpc_client()->GetLastError() == |
192 NACL_SRPC_RESULT_APP_ERROR) { | |
193 // The error string is only present if the error was sent back from llc | |
194 TranslateFailed(params.outs()[3]->arrays.str); | |
195 } else { | |
196 TranslateFailed("Compile StreamEnd internal error"); | |
197 } | |
190 return; | 198 return; |
191 } | 199 } |
192 // LLC returns values that are used to determine how linking is done. | 200 // LLC returns values that are used to determine how linking is done. |
193 int is_shared_library = (params.outs()[0]->u.ival != 0); | 201 int is_shared_library = (params.outs()[0]->u.ival != 0); |
194 nacl::string soname = params.outs()[1]->arrays.str; | 202 nacl::string soname = params.outs()[1]->arrays.str; |
195 nacl::string lib_dependencies = params.outs()[2]->arrays.str; | 203 nacl::string lib_dependencies = params.outs()[2]->arrays.str; |
196 PLUGIN_PRINTF(("PnaclCoordinator: compile (translator=%p) succeeded" | 204 PLUGIN_PRINTF(("PnaclCoordinator: compile (translator=%p) succeeded" |
197 " is_shared_library=%d, soname='%s', lib_dependencies='%s')\n", | 205 " is_shared_library=%d, soname='%s', lib_dependencies='%s')\n", |
198 this, is_shared_library, soname.c_str(), | 206 this, is_shared_library, soname.c_str(), |
199 lib_dependencies.c_str())); | 207 lib_dependencies.c_str())); |
200 | 208 |
201 // Shut down the llc subprocess. | 209 // Shut down the llc subprocess. |
202 RegisterReverseInterface(NULL); | 210 NaClXMutexLock(&subprocess_mu_); |
203 llc_subprocess.reset(NULL); | 211 llc_subprocess_.reset(NULL); |
204 if (SubprocessesShouldDie()) { | 212 NaClXMutexUnlock(&subprocess_mu_); |
205 TranslateFailed("stopped by coordinator."); | |
206 return; | |
207 } | |
208 | 213 |
209 if(!RunLdSubprocess(is_shared_library, soname, lib_dependencies)) { | 214 if(!RunLdSubprocess(is_shared_library, soname, lib_dependencies)) { |
210 return; | 215 return; |
211 } | 216 } |
212 pp::Core* core = pp::Module::Get()->core(); | 217 pp::Core* core = pp::Module::Get()->core(); |
213 core->CallOnMainThread(0, report_translate_finished_, PP_OK); | 218 core->CallOnMainThread(0, report_translate_finished_, PP_OK); |
214 } | 219 } |
215 | 220 |
216 bool PnaclTranslateThread::RunLdSubprocess(int is_shared_library, | 221 bool PnaclTranslateThread::RunLdSubprocess(int is_shared_library, |
217 const nacl::string& soname, | 222 const nacl::string& soname, |
218 const nacl::string& lib_dependencies | 223 const nacl::string& lib_dependencies |
219 ) { | 224 ) { |
220 ErrorInfo error_info; | 225 ErrorInfo error_info; |
221 nacl::scoped_ptr<NaClSubprocess> ld_subprocess( | |
222 StartSubprocess(PnaclUrls::GetLdUrl(), ld_manifest_, &error_info)); | |
223 if (ld_subprocess == NULL) { | |
224 TranslateFailed("Link process could not be created: " + | |
225 error_info.message()); | |
226 return false; | |
227 } | |
228 // Run LD. | |
229 SrpcParams params; | 226 SrpcParams params; |
230 | |
231 // Reset object file for reading first. | 227 // Reset object file for reading first. |
232 if (!obj_file_->Reset()) { | 228 if (!obj_file_->Reset()) { |
233 TranslateFailed("Link process could not reset object file"); | 229 TranslateFailed("Link process could not reset object file"); |
234 return false; | 230 return false; |
235 } | 231 } |
236 nacl::DescWrapper* ld_in_file = obj_file_->get_wrapper(); | 232 nacl::DescWrapper* ld_in_file = obj_file_->get_wrapper(); |
237 nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper(); | 233 nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper(); |
238 PluginReverseInterface* ld_reverse = | 234 |
239 ld_subprocess->service_runtime()->rev_interface(); | 235 { |
240 ld_reverse->AddQuotaManagedFile(nexe_file_->identifier(), | 236 // Create LD process |
241 nexe_file_->write_file_io()); | 237 nacl::MutexLocker ml(&subprocess_mu_); |
242 RegisterReverseInterface(ld_reverse); | 238 ld_subprocess_.reset( |
243 if (!ld_subprocess->InvokeSrpcMethod("RunWithDefaultCommandLine", | 239 StartSubprocess(PnaclUrls::GetLdUrl(), ld_manifest_, &error_info)); |
240 if (ld_subprocess_ == NULL) { | |
241 TranslateFailed("Link process could not be created: " + | |
242 error_info.message()); | |
243 return false; | |
244 } | |
245 PluginReverseInterface* ld_reverse = | |
246 ld_subprocess_->service_runtime()->rev_interface(); | |
247 ld_reverse->AddQuotaManagedFile(nexe_file_->identifier(), | |
248 nexe_file_->write_file_io()); | |
249 } | |
250 // Run LD. | |
251 if (!ld_subprocess_->InvokeSrpcMethod("RunWithDefaultCommandLine", | |
244 "hhiss", | 252 "hhiss", |
245 ¶ms, | 253 ¶ms, |
246 ld_in_file->desc(), | 254 ld_in_file->desc(), |
247 ld_out_file->desc(), | 255 ld_out_file->desc(), |
248 is_shared_library, | 256 is_shared_library, |
249 soname.c_str(), | 257 soname.c_str(), |
250 lib_dependencies.c_str())) { | 258 lib_dependencies.c_str())) { |
251 TranslateFailed("link failed."); | 259 TranslateFailed("link failed."); |
252 return false; | 260 return false; |
253 } | 261 } |
254 PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n", | 262 PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n", |
255 this)); | 263 this)); |
256 // Shut down the ld subprocess. | 264 // Shut down the ld subprocess. |
257 RegisterReverseInterface(NULL); | 265 NaClXMutexLock(&subprocess_mu_); |
258 ld_subprocess.reset(NULL); | 266 ld_subprocess_.reset(NULL); |
259 if (SubprocessesShouldDie()) { | 267 NaClXMutexUnlock(&subprocess_mu_); |
260 TranslateFailed("stopped by coordinator."); | |
261 return false; | |
262 } | |
263 return true; | 268 return true; |
264 } | 269 } |
265 | 270 |
266 void PnaclTranslateThread::TranslateFailed(const nacl::string& error_string) { | 271 void PnaclTranslateThread::TranslateFailed(const nacl::string& error_string) { |
267 PLUGIN_PRINTF(("PnaclTranslateThread::TranslateFailed (error_string='%s')\n", | 272 PLUGIN_PRINTF(("PnaclTranslateThread::TranslateFailed (error_string='%s')\n", |
268 error_string.c_str())); | 273 error_string.c_str())); |
269 pp::Core* core = pp::Module::Get()->core(); | 274 pp::Core* core = pp::Module::Get()->core(); |
270 if (coordinator_error_info_->message().empty()) { | 275 if (coordinator_error_info_->message().empty()) { |
271 // Only use our message if one hasn't already been set by the coordinator | 276 // Only use our message if one hasn't already been set by the coordinator |
272 // (e.g. pexe load failed). | 277 // (e.g. pexe load failed). |
273 coordinator_error_info_->SetReport(ERROR_UNKNOWN, | 278 coordinator_error_info_->SetReport(ERROR_UNKNOWN, |
274 nacl::string("PnaclCoordinator: ") + | 279 nacl::string("PnaclCoordinator: ") + |
275 error_string); | 280 error_string); |
276 } | 281 } |
277 core->CallOnMainThread(0, report_translate_finished_, PP_ERROR_FAILED); | 282 core->CallOnMainThread(0, report_translate_finished_, PP_ERROR_FAILED); |
278 } | 283 } |
279 | 284 |
280 // This synchronization method (using the pointer directly in the | 285 void PnaclTranslateThread::AbortSubprocesses() { |
281 // translation thread, setting a copy here, and calling shutdown on the | 286 PLUGIN_PRINTF(("PnaclTranslateThread::AbortSubprocesses\n")); |
282 // main thread) is safe only because only the translation thread sets | |
283 // the copy, and the shutdown method is thread-safe. This method must be | |
284 // called on the translation thread before any RPCs are called, and called | |
285 // again with NULL before the object is destroyed. | |
286 void PnaclTranslateThread::RegisterReverseInterface( | |
287 PluginReverseInterface *iface) { | |
288 nacl::MutexLocker ml(&subprocess_mu_); | |
289 current_rev_interface_ = iface; | |
290 } | |
291 | |
292 | |
293 bool PnaclTranslateThread::SubprocessesShouldDie() { | |
294 nacl::MutexLocker ml(&subprocess_mu_); | |
295 return subprocesses_should_die_; | |
296 } | |
297 | |
298 void PnaclTranslateThread::SetSubprocessesShouldDie() { | |
299 PLUGIN_PRINTF(("PnaclTranslateThread::SetSubprocessesShouldDie\n")); | |
300 NaClXMutexLock(&subprocess_mu_); | 287 NaClXMutexLock(&subprocess_mu_); |
301 subprocesses_should_die_ = true; | 288 if (llc_subprocess_ != NULL) llc_subprocess_->service_runtime()->Shutdown(); |
jvoung (off chromium)
2012/08/02 23:24:10
Since set llc_subprocess is not set to null after,
Derek Schuff
2012/08/02 23:46:45
I *think* so, but it actually goes pretty deep int
| |
302 if (current_rev_interface_) { | 289 if (ld_subprocess_ != NULL) ld_subprocess_->service_runtime()->Shutdown(); |
303 current_rev_interface_->ShutDown(); | |
304 current_rev_interface_ = NULL; | |
305 } | |
306 NaClXMutexUnlock(&subprocess_mu_); | 290 NaClXMutexUnlock(&subprocess_mu_); |
307 nacl::MutexLocker ml(&cond_mu_); | 291 nacl::MutexLocker ml(&cond_mu_); |
308 done_ = true; | 292 done_ = true; |
293 // Free all buffered bitcode chunks | |
294 data_buffers_.clear(); | |
309 NaClXCondVarSignal(&buffer_cond_); | 295 NaClXCondVarSignal(&buffer_cond_); |
310 } | 296 } |
311 | 297 |
312 PnaclTranslateThread::~PnaclTranslateThread() { | 298 PnaclTranslateThread::~PnaclTranslateThread() { |
313 PLUGIN_PRINTF(("~PnaclTranslateThread (translate_thread=%p)\n", this)); | 299 PLUGIN_PRINTF(("~PnaclTranslateThread (translate_thread=%p)\n", this)); |
314 SetSubprocessesShouldDie(); | 300 AbortSubprocesses(); |
jvoung (off chromium)
2012/08/02 23:24:10
AbortSubprocesses() is called from multiple destru
Derek Schuff
2012/08/02 23:46:45
Other than potentially service_runtime Shutdown (a
| |
315 NaClThreadJoin(translate_thread_.get()); | 301 NaClThreadJoin(translate_thread_.get()); |
316 PLUGIN_PRINTF(("~PnaclTranslateThread joined\n")); | 302 PLUGIN_PRINTF(("~PnaclTranslateThread joined\n")); |
303 NaClCondVarDtor(&buffer_cond_); | |
304 NaClMutexDtor(&cond_mu_); | |
317 NaClMutexDtor(&subprocess_mu_); | 305 NaClMutexDtor(&subprocess_mu_); |
318 } | 306 } |
319 | 307 |
320 } // namespace plugin | 308 } // namespace plugin |
OLD | NEW |