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