1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
|
/* -*- c++ -*- */
/*
* Copyright (c) 2012 The Chromium Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// A class containing information regarding a socket connection to a
// service runtime instance.
#ifndef NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_SERVICE_RUNTIME_H_
#define NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_SERVICE_RUNTIME_H_
#include <set>
#include "native_client/src/include/nacl_macros.h"
#include "native_client/src/include/nacl_scoped_ptr.h"
#include "native_client/src/include/nacl_string.h"
#include "native_client/src/shared/platform/nacl_sync.h"
#include "native_client/src/shared/srpc/nacl_srpc.h"
#include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
#include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h"
#include "native_client/src/trusted/reverse_service/reverse_service.h"
#include "native_client/src/trusted/weak_ref/weak_ref.h"
#include "ppapi/cpp/completion_callback.h"
#include "ppapi/native_client/src/trusted/plugin/utility.h"
struct NaClFileInfo;
namespace nacl {
class DescWrapper;
} // namespace
namespace plugin {
class ErrorInfo;
class Plugin;
class SelLdrLauncherChrome;
class SrpcClient;
class ServiceRuntime;
// Struct of params used by StartSelLdr. Use a struct so that callback
// creation templates aren't overwhelmed with too many parameters.
struct SelLdrStartParams {
SelLdrStartParams(const nacl::string& url,
const PP_NaClFileInfo& file_info,
bool uses_irt,
bool uses_ppapi,
bool enable_dyncode_syscalls,
bool enable_exception_handling,
bool enable_crash_throttling)
: url(url),
file_info(file_info),
uses_irt(uses_irt),
uses_ppapi(uses_ppapi),
enable_dyncode_syscalls(enable_dyncode_syscalls),
enable_exception_handling(enable_exception_handling),
enable_crash_throttling(enable_crash_throttling) {
}
nacl::string url;
PP_NaClFileInfo file_info;
bool uses_irt;
bool uses_ppapi;
bool enable_dev_interfaces;
bool enable_dyncode_syscalls;
bool enable_exception_handling;
bool enable_crash_throttling;
};
// Callback resources are essentially our continuation state.
struct OpenManifestEntryResource {
public:
OpenManifestEntryResource(const std::string& target_url,
struct NaClFileInfo* finfo,
bool* op_complete)
: url(target_url),
file_info(finfo),
op_complete_ptr(op_complete) {}
~OpenManifestEntryResource();
std::string url;
struct NaClFileInfo* file_info;
PP_NaClFileInfo pp_file_info;
bool* op_complete_ptr;
};
// Do not invoke from the main thread, since the main methods will
// invoke CallOnMainThread and then wait on a condvar for the task to
// complete: if invoked from the main thread, the main method not
// returning (and thus unblocking the main thread) means that the
// main-thread continuation methods will never get called, and thus
// we'd get a deadlock.
class PluginReverseInterface: public nacl::ReverseInterface {
public:
PluginReverseInterface(nacl::WeakRefAnchor* anchor,
PP_Instance pp_instance,
ServiceRuntime* service_runtime,
pp::CompletionCallback init_done_cb,
pp::CompletionCallback crash_cb);
virtual ~PluginReverseInterface();
void ShutDown();
virtual void DoPostMessage(nacl::string message);
virtual void StartupInitializationComplete();
virtual bool OpenManifestEntry(nacl::string url_key,
struct NaClFileInfo *info);
virtual void ReportCrash();
virtual void ReportExitStatus(int exit_status);
// TODO(teravest): Remove this method once it's gone from
// nacl::ReverseInterface.
virtual int64_t RequestQuotaForWrite(nacl::string file_id,
int64_t offset,
int64_t bytes_to_write);
protected:
virtual void OpenManifestEntry_MainThreadContinuation(
OpenManifestEntryResource* p,
int32_t err);
virtual void StreamAsFile_MainThreadContinuation(
OpenManifestEntryResource* p,
int32_t result);
private:
nacl::WeakRefAnchor* anchor_; // holds a ref
// Should be used only in main thread in WeakRef-protected callbacks.
PP_Instance pp_instance_;
ServiceRuntime* service_runtime_;
NaClMutex mu_;
NaClCondVar cv_;
bool shutting_down_;
pp::CompletionCallback init_done_cb_;
pp::CompletionCallback crash_cb_;
};
// ServiceRuntime abstracts a NativeClient sel_ldr instance.
class ServiceRuntime {
public:
// TODO(sehr): This class should also implement factory methods, using the
// Start method below.
ServiceRuntime(Plugin* plugin,
PP_Instance pp_instance,
bool main_service_runtime,
bool uses_nonsfi_mode,
pp::CompletionCallback init_done_cb,
pp::CompletionCallback crash_cb);
// The destructor terminates the sel_ldr process.
~ServiceRuntime();
// Spawn the sel_ldr instance.
void StartSelLdr(const SelLdrStartParams& params,
pp::CompletionCallback callback);
// If starting sel_ldr from a background thread, wait for sel_ldr to
// actually start. Returns |false| if timed out waiting for the process
// to start. Otherwise, returns |true| if StartSelLdr is complete
// (either successfully or unsuccessfully).
bool WaitForSelLdrStart();
// Signal to waiting threads that StartSelLdr is complete (either
// successfully or unsuccessfully).
void SignalStartSelLdrDone();
// If starting the nexe from a background thread, wait for the nexe to
// actually start. Returns |true| is the nexe started successfully.
bool WaitForNexeStart();
// Signal to waiting threads that LoadNexeAndStart is complete (either
// successfully or unsuccessfully).
void SignalNexeStarted(bool ok);
// Establish an SrpcClient to the sel_ldr instance and start the nexe.
// This function must be called on the main thread.
// This function must only be called once.
void StartNexe();
// Starts the application channel to the nexe.
SrpcClient* SetupAppChannel();
bool RemoteLog(int severity, const nacl::string& msg);
Plugin* plugin() const { return plugin_; }
void Shutdown();
bool main_service_runtime() const { return main_service_runtime_; }
private:
NACL_DISALLOW_COPY_AND_ASSIGN(ServiceRuntime);
bool StartNexeInternal();
bool SetupCommandChannel();
bool InitReverseService();
bool StartModule();
void ReapLogs();
void ReportLoadError(const ErrorInfo& error_info);
NaClSrpcChannel command_channel_;
Plugin* plugin_;
PP_Instance pp_instance_;
bool main_service_runtime_;
bool uses_nonsfi_mode_;
nacl::ReverseService* reverse_service_;
nacl::scoped_ptr<SelLdrLauncherChrome> subprocess_;
nacl::WeakRefAnchor* anchor_;
PluginReverseInterface* rev_interface_;
// Mutex and CondVar to protect start_sel_ldr_done_ and nexe_started_.
NaClMutex mu_;
NaClCondVar cond_;
bool start_sel_ldr_done_;
bool start_nexe_done_;
bool nexe_started_ok_;
NaClHandle bootstrap_channel_;
};
} // namespace plugin
#endif // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_SERVICE_RUNTIME_H_
|