debugging.c revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
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 3 * found in the LICENSE file. 4 */ 5 6/** @file debugging.c 7 * This example, is a modified version of hello world. It will start a second 8 * thread and cause that thread to crash via a NULL dereference. 9 */ 10#include <stdio.h> 11#include <stdlib.h> 12#include <string.h> 13 14#include "ppapi/c/pp_errors.h" 15#include "ppapi/c/pp_module.h" 16#include "ppapi/c/pp_var.h" 17#include "ppapi/c/ppb.h" 18#include "ppapi/c/ppb_core.h" 19#include "ppapi/c/ppb_instance.h" 20#include "ppapi/c/ppb_messaging.h" 21#include "ppapi/c/ppb_var.h" 22#include "ppapi/c/ppp.h" 23#include "ppapi/c/ppp_instance.h" 24#include "ppapi/c/ppp_messaging.h" 25 26#include <pthread.h> 27 28#include "error_handling/error_handling.h" 29 30PPB_Messaging* ppb_messaging_interface = NULL; 31PPB_Var* ppb_var_interface = NULL; 32PPB_Core* ppb_core_interface = NULL; 33 34pthread_t g_NexeThread; 35pthread_t g_PPAPIThread; 36PP_Instance g_Instance; 37 38volatile int g_CrashTime = 0; 39 40void PostMessage(const char* str); 41 42void layer5(int x, int y) { 43 if (g_CrashTime) { 44 *(volatile int*)x = y; 45 } 46} 47 48void layer4(int x) { layer5(x, 1); } 49 50void layer3(int a, int b, int c) { layer4(a + b + c); } 51 52void layer2(int i, int j) { layer3(i, j, 7); } 53 54void layer1(int s, int t) { 55 int* junk = (int*)alloca(sizeof(int) * 1234); 56 junk[0] = s + 5; 57 layer2(junk[0], t + 1); 58} 59 60void* NexeMain(void* data) { 61 PostMessage("Running Boom thread."); 62 while (1) { 63 layer1(2, 9); 64 } 65 return NULL; 66} 67 68/** 69 * Creates new string PP_Var from C string. The resulting object will be a 70 * refcounted string object. It will be AddRef()ed for the caller. When the 71 * caller is done with it, it should be Release()d. 72 * @param[in] str C string to be converted to PP_Var 73 * @return PP_Var containing string. 74 */ 75static struct PP_Var CStrToVar(const char* str) { 76 if (ppb_var_interface != NULL) { 77 return ppb_var_interface->VarFromUtf8(str, strlen(str)); 78 } 79 return PP_MakeUndefined(); 80} 81 82static void PostCompletionCallback(void* user_data, int32_t result) { 83 const char* str = (const char*)user_data; 84 ppb_messaging_interface->PostMessage(g_Instance, CStrToVar(str)); 85 free(user_data); 86} 87 88void PostMessage(const char* str) { 89 struct PP_CompletionCallback cb; 90 91 if (NULL == str) 92 return; 93 if (NULL == ppb_messaging_interface) 94 return; 95 if (0 == g_Instance) 96 return; 97 98 if (strncmp(str, "ERR:", 4)) { 99 fprintf(stderr, "%s\n", str); 100 fflush(stderr); 101 } else { 102 fprintf(stdout, "%s\n", str); 103 fflush(stdout); 104 } 105 106 /* If on Main Pepper thread, then call interface directly. */ 107 if (pthread_self() == g_PPAPIThread) { 108 ppb_messaging_interface->PostMessage(g_Instance, CStrToVar(str)); 109 return; 110 } 111 112 /* Otherwise use call on main thread. */ 113 cb = PP_MakeCompletionCallback(PostCompletionCallback, strdup(str)); 114 ppb_core_interface->CallOnMainThread(0, cb, 0); 115} 116 117void DumpJson(const char* json) { 118 char* out = (char*)malloc(strlen(json) + 5); 119 strcpy(out, "TRC: "); 120 strcat(out, json); 121 122 PostMessage(out); 123 free(out); 124} 125/** 126 * Called when the NaCl module is instantiated on the web page. The identifier 127 * of the new instance will be passed in as the first argument (this value is 128 * generated by the browser and is an opaque handle). This is called for each 129 * instantiation of the NaCl module, which is each time the <embed> tag for 130 * this module is encountered. 131 * 132 * If this function reports a failure (by returning @a PP_FALSE), the NaCl 133 * module will be deleted and DidDestroy will be called. 134 * @param[in] instance The identifier of the new instance representing this 135 * NaCl module. 136 * @param[in] argc The number of arguments contained in @a argn and @a argv. 137 * @param[in] argn An array of argument names. These argument names are 138 * supplied in the <embed> tag, for example: 139 * <embed id="nacl_module" dimensions="2"> 140 * will produce two arguments, one named "id" and one named "dimensions". 141 * @param[in] argv An array of argument values. These are the values of the 142 * arguments listed in the <embed> tag. In the above example, there will 143 * be two elements in this array, "nacl_module" and "2". The indices of 144 * these values match the indices of the corresponding names in @a argn. 145 * @return @a PP_TRUE on success. 146 */ 147static PP_Bool Instance_DidCreate(PP_Instance instance, 148 uint32_t argc, 149 const char* argn[], 150 const char* argv[]) { 151 g_Instance = instance; 152 g_PPAPIThread = pthread_self(); 153 154 PostMessage("LOG: DidCreate"); 155 156 /* Request exception callbacks with JSON. */ 157 EHRequestExceptionsJson(DumpJson); 158 159 /* Report back if the request was honored. */ 160 if (!EHHanderInstalled()) { 161 PostMessage("LOG: Stack traces not available, so don't expect them.\n"); 162 } else { 163 PostMessage("LOG: Stack traces are on."); 164 } 165 pthread_create(&g_NexeThread, NULL, NexeMain, NULL); 166 return PP_TRUE; 167} 168 169/** 170 * Called when the NaCl module is destroyed. This will always be called, 171 * even if DidCreate returned failure. This routine should deallocate any data 172 * associated with the instance. 173 * @param[in] instance The identifier of the instance representing this NaCl 174 * module. 175 */ 176static void Instance_DidDestroy(PP_Instance instance) {} 177 178/** 179 * Called when the position, the size, or the clip rect of the element in the 180 * browser that corresponds to this NaCl module has changed. 181 * @param[in] instance The identifier of the instance representing this NaCl 182 * module. 183 * @param[in] position The location on the page of this NaCl module. This is 184 * relative to the top left corner of the viewport, which changes as the 185 * page is scrolled. 186 * @param[in] clip The visible region of the NaCl module. This is relative to 187 * the top left of the plugin's coordinate system (not the page). If the 188 * plugin is invisible, @a clip will be (0, 0, 0, 0). 189 */ 190static void Instance_DidChangeView(PP_Instance instance, 191 PP_Resource view_resource) {} 192 193/** 194 * Notification that the given NaCl module has gained or lost focus. 195 * Having focus means that keyboard events will be sent to the NaCl module 196 * represented by @a instance. A NaCl module's default condition is that it 197 * will not have focus. 198 * 199 * Note: clicks on NaCl modules will give focus only if you handle the 200 * click event. You signal if you handled it by returning @a true from 201 * HandleInputEvent. Otherwise the browser will bubble the event and give 202 * focus to the element on the page that actually did end up consuming it. 203 * If you're not getting focus, check to make sure you're returning true from 204 * the mouse click in HandleInputEvent. 205 * @param[in] instance The identifier of the instance representing this NaCl 206 * module. 207 * @param[in] has_focus Indicates whether this NaCl module gained or lost 208 * event focus. 209 */ 210static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {} 211 212/** 213 * Handler that gets called after a full-frame module is instantiated based on 214 * registered MIME types. This function is not called on NaCl modules. This 215 * function is essentially a place-holder for the required function pointer in 216 * the PPP_Instance structure. 217 * @param[in] instance The identifier of the instance representing this NaCl 218 * module. 219 * @param[in] url_loader A PP_Resource an open PPB_URLLoader instance. 220 * @return PP_FALSE. 221 */ 222static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance, 223 PP_Resource url_loader) { 224 /* NaCl modules do not need to handle the document load function. */ 225 return PP_FALSE; 226} 227 228/** 229 * Handles message from JavaScript. 230 * 231 * Any message from JS is a request to cause the main thread to crash. 232 */ 233static void Messaging_HandleMessage(PP_Instance instance, 234 struct PP_Var message) { 235 PostMessage("LOG: Got BOOM"); 236 g_CrashTime = 1; 237} 238 239/** 240 * Entry points for the module. 241 * Initialize needed interfaces: PPB_Core, PPB_Messaging and PPB_Var. 242 * @param[in] a_module_id module ID 243 * @param[in] get_browser pointer to PPB_GetInterface 244 * @return PP_OK on success, any other value on failure. 245 */ 246PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id, 247 PPB_GetInterface get_browser) { 248 ppb_messaging_interface = 249 (PPB_Messaging*)(get_browser(PPB_MESSAGING_INTERFACE)); 250 ppb_var_interface = (PPB_Var*)(get_browser(PPB_VAR_INTERFACE)); 251 ppb_core_interface = (PPB_Core*)(get_browser(PPB_CORE_INTERFACE)); 252 return PP_OK; 253} 254 255/** 256 * Returns an interface pointer for the interface of the given name, or NULL 257 * if the interface is not supported. 258 * @param[in] interface_name name of the interface 259 * @return pointer to the interface 260 */ 261PP_EXPORT const void* PPP_GetInterface(const char* interface_name) { 262 if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) { 263 static PPP_Instance instance_interface = { 264 &Instance_DidCreate, 265 &Instance_DidDestroy, 266 &Instance_DidChangeView, 267 &Instance_DidChangeFocus, 268 &Instance_HandleDocumentLoad, 269 }; 270 return &instance_interface; 271 } 272 if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0) { 273 static PPP_Messaging messaging_interface = { 274 &Messaging_HandleMessage, 275 }; 276 return &messaging_interface; 277 } 278 return NULL; 279} 280 281/** 282 * Called before the plugin module is unloaded. 283 */ 284PP_EXPORT void PPP_ShutdownModule() {} 285