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