Home | History | Annotate | Download | only in debugging
      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 
     30 PPB_Messaging* ppb_messaging_interface = NULL;
     31 PPB_Var* ppb_var_interface = NULL;
     32 PPB_Core* ppb_core_interface = NULL;
     33 
     34 pthread_t g_NexeThread;
     35 pthread_t g_PPAPIThread;
     36 PP_Instance g_Instance;
     37 
     38 volatile int g_CrashTime = 0;
     39 
     40 void PostMessage(const char* str);
     41 
     42 void layer5(int x, int y) {
     43   if (g_CrashTime) {
     44     *(volatile int*)x = y;
     45   }
     46 }
     47 
     48 void layer4(int x) { layer5(x, 1); }
     49 
     50 void layer3(int a, int b, int c) { layer4(a + b + c); }
     51 
     52 void layer2(int i, int j) { layer3(i, j, 7); }
     53 
     54 void 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 
     60 void* NexeMain(void* data) {
     61   PostMessage("Running Boom thread.");
     62   while (1) {
     63     layer1(2, 9);
     64   }
     65   return NULL;
     66 }
     67 
     68 void PostMessage(const char* str) {
     69   if (NULL == str)
     70     return;
     71   if (NULL == ppb_messaging_interface)
     72     return;
     73   if (0 == g_Instance)
     74     return;
     75 
     76   fprintf(stdout, "%s\n", str);
     77   fflush(stdout);
     78 
     79   if (ppb_var_interface != NULL) {
     80     struct PP_Var var = ppb_var_interface->VarFromUtf8(str, strlen(str));
     81     ppb_messaging_interface->PostMessage(g_Instance, var);
     82     ppb_var_interface->Release(var);
     83   }
     84 }
     85 
     86 void DumpJson(const char* json) {
     87   const char kTrcPrefix[] = "TRC: ";
     88   size_t size = sizeof(kTrcPrefix) + strlen(json) + 1;  // +1 for NULL.
     89   char* out = (char*)malloc(size);
     90   strcpy(out, kTrcPrefix);
     91   strcat(out, json);
     92 
     93   PostMessage(out);
     94   free(out);
     95 }
     96 
     97 static PP_Bool Instance_DidCreate(PP_Instance instance,
     98                                   uint32_t argc,
     99                                   const char* argn[],
    100                                   const char* argv[]) {
    101   g_Instance = instance;
    102   g_PPAPIThread = pthread_self();
    103 
    104   PostMessage("LOG: DidCreate");
    105 
    106   /* Request exception callbacks with JSON. */
    107   EHRequestExceptionsJson(DumpJson);
    108 
    109   /* Report back if the request was honored. */
    110   if (!EHHanderInstalled()) {
    111     PostMessage("LOG: Stack traces not available, so don't expect them.\n");
    112   } else {
    113     PostMessage("LOG: Stack traces are on.");
    114   }
    115   pthread_create(&g_NexeThread, NULL, NexeMain, NULL);
    116   return PP_TRUE;
    117 }
    118 
    119 static void Instance_DidDestroy(PP_Instance instance) {}
    120 
    121 static void Instance_DidChangeView(PP_Instance instance,
    122                                    PP_Resource view_resource) {}
    123 
    124 static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {}
    125 
    126 static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
    127                                            PP_Resource url_loader) {
    128   return PP_FALSE;
    129 }
    130 
    131 /**
    132  * Handles message from JavaScript.
    133  *
    134  * Any message from JS is a request to cause the main thread to crash.
    135  */
    136 static void Messaging_HandleMessage(PP_Instance instance,
    137                                     struct PP_Var message) {
    138   PostMessage("LOG: Got BOOM");
    139   g_CrashTime = 1;
    140 }
    141 
    142 PP_EXPORT int32_t
    143 PPP_InitializeModule(PP_Module a_module_id, PPB_GetInterface get_browser) {
    144   ppb_messaging_interface =
    145       (PPB_Messaging*)(get_browser(PPB_MESSAGING_INTERFACE));
    146   ppb_var_interface = (PPB_Var*)(get_browser(PPB_VAR_INTERFACE));
    147   ppb_core_interface = (PPB_Core*)(get_browser(PPB_CORE_INTERFACE));
    148   return PP_OK;
    149 }
    150 
    151 PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
    152   if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
    153     static PPP_Instance instance_interface = {
    154         &Instance_DidCreate,
    155         &Instance_DidDestroy,
    156         &Instance_DidChangeView,
    157         &Instance_DidChangeFocus,
    158         &Instance_HandleDocumentLoad,
    159     };
    160     return &instance_interface;
    161   }
    162   if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0) {
    163     static PPP_Messaging messaging_interface = {
    164       &Messaging_HandleMessage,
    165     };
    166     return &messaging_interface;
    167   }
    168   return NULL;
    169 }
    170 
    171 PP_EXPORT void PPP_ShutdownModule() {}
    172