Skip to content
Snippets Groups Projects
Commit 8c100589 authored by deuce's avatar deuce
Browse files

Add hacky debugging wrappers for JS request functions

parent dcc1c21e
No related branches found
No related tags found
No related merge requests found
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __unix__
#define XP_UNIX
#else
#define XP_PC
#define XP_WIN
#endif
#include <jsapi.h>
#include "threadwrap.h"
#include "js_request.h"
#ifdef DEBUG_JS_REQUESTS
#define DEBUG
#define JS_THREADSAFE
#include <jscntxt.h>
enum last_request_type {
LAST_REQUEST_TYPE_NONE
,LAST_REQUEST_TYPE_BEGIN
,LAST_REQUEST_TYPE_END
,LAST_REQUEST_TYPE_SUSPEND
,LAST_REQUEST_TYPE_RESUME
};
static const char *type_names[5]={"None", "BeginRequest", "EndRequest", "SuspendRequest", "ResumeRequest"};
struct request_log {
JSContext* cx;
enum last_request_type type;
const char* file;
unsigned long line;
struct request_log* next;
struct request_log* prev;
};
static struct request_log* first_request;
static int initialized=0;
static pthread_mutex_t req_mutex;
static char str[1024];
static void logstr(void)
{
FILE *f;
if((f=fopen("../data/logs/JS_RequestErrors.log", "a"))!=NULL) {
fputs(str, f);
fclose(f);
}
else {
fputs(str, stderr);
}
}
static struct request_log *match_request(JSContext *cx)
{
struct request_log *ent;
for(ent=first_request; ent != NULL; ent=ent->next) {
if(ent->cx==cx)
return(ent);
}
ent=malloc(sizeof(struct request_log));
if(ent != NULL) {
memset(ent, 0, sizeof(struct request_log));
ent->cx=cx;
ent->type=LAST_REQUEST_TYPE_NONE;
ent->prev=NULL;
ent->next=first_request;
if(first_request != NULL) {
first_request->prev=ent;
}
first_request=ent;
return(ent);
}
return(NULL);
}
static void initialize_request(void)
{
pthread_mutex_init(&req_mutex, NULL);
initialized=1;
}
void js_debug_beginrequest(JSContext *cx, const char *file, unsigned long line)
{
struct request_log *req;
if(!initialized)
initialize_request();
pthread_mutex_lock(&req_mutex);
req=match_request(cx);
if(req==NULL) {
strcpy(str,"Missing req in Begin\n");
logstr();
return;
}
switch(req->type) {
case LAST_REQUEST_TYPE_NONE:
case LAST_REQUEST_TYPE_END:
break;
case LAST_REQUEST_TYPE_BEGIN:
case LAST_REQUEST_TYPE_SUSPEND:
case LAST_REQUEST_TYPE_RESUME:
sprintf(str,"Begin after %s from %s:%u at %s:%u\n",type_names[req->type],req->file,req->line,file,line);
logstr();
break;
}
switch(cx->requestDepth) {
case 0:
break;
case 1:
default:
sprintf(str,"depth=%u at Begin after %s from %s:%u at %s:%u\n",cx->requestDepth,type_names[req->type],req->file,req->line,file,line);
logstr();
break;
}
req->type=LAST_REQUEST_TYPE_BEGIN;
req->file=file;
req->line=line;
JS_BeginRequest(cx);
pthread_mutex_unlock(&req_mutex);
}
void js_debug_endrequest(JSContext *cx, const char *file, unsigned long line)
{
struct request_log *req;
if(!initialized)
initialize_request();
pthread_mutex_lock(&req_mutex);
req=match_request(cx);
if(req==NULL) {
strcpy(str,"Missing req in End\n");
logstr();
return;
}
switch(req->type) {
case LAST_REQUEST_TYPE_BEGIN:
if(req->file) {
if(strcmp(req->file, file) != 0 || line < req->line) {
sprintf(str,"Suspicious End after %s from %s:%u at %s:%u\n",type_names[req->type],req->file,req->line,file,line);
}
break;
}
case LAST_REQUEST_TYPE_RESUME:
break;
case LAST_REQUEST_TYPE_NONE:
case LAST_REQUEST_TYPE_END:
case LAST_REQUEST_TYPE_SUSPEND:
sprintf(str,"End after %s from %s:%u at %s:%u\n",type_names[req->type],req->file,req->line,file,line);
logstr();
break;
}
switch(cx->requestDepth) {
case 0:
default:
sprintf(str,"depth=%u at End after %s from %s:%u at %s:%u\n",cx->requestDepth,type_names[req->type],req->file,req->line,file,line);
logstr();
break;
case 1:
break;
}
req->type=LAST_REQUEST_TYPE_END;
req->file=file;
req->line=line;
JS_EndRequest(cx);
if(req->prev != NULL)
req->prev->next=req->next;
if(req->next != NULL)
req->next->prev=req->prev;
if(first_request==req) {
if(req->prev != NULL)
first_request=req->prev;
else
first_request=req->next;
}
free(req);
pthread_mutex_unlock(&req_mutex);
}
jsrefcount js_debug_suspendrequest(JSContext *cx, const char *file, unsigned long line)
{
struct request_log *req;
jsrefcount ret;
if(!initialized)
initialize_request();
pthread_mutex_lock(&req_mutex);
req=match_request(cx);
if(req==NULL) {
strcpy(str,"Missing req in Suspend\n");
logstr();
return;
}
switch(req->type) {
case LAST_REQUEST_TYPE_BEGIN:
case LAST_REQUEST_TYPE_RESUME:
break;
case LAST_REQUEST_TYPE_NONE:
if(req->file==NULL) /* Assumed to be a provided request */
break;
case LAST_REQUEST_TYPE_END:
case LAST_REQUEST_TYPE_SUSPEND:
sprintf(str,"Suspend after %s from %s:%u at %s:%u\n",type_names[req->type],req->file,req->line,file,line);
logstr();
break;
}
switch(cx->requestDepth) {
case 0:
default:
sprintf(str,"depth=%u at Suspend after %s from %s:%u at %s:%u\n",cx->requestDepth,type_names[req->type],req->file,req->line,file,line);
logstr();
break;
case 1:
break;
}
req->type=LAST_REQUEST_TYPE_SUSPEND;
req->file=file;
req->line=line;
ret=JS_SuspendRequest(cx);
pthread_mutex_unlock(&req_mutex);
return(ret);
}
void js_debug_resumerequest(JSContext *cx, jsrefcount rc, const char *file, unsigned long line)
{
struct request_log *req;
if(!initialized)
initialize_request();
pthread_mutex_lock(&req_mutex);
req=match_request(cx);
if(req==NULL) {
strcpy(str,"Missing req in Resume\n");
logstr();
return;
}
switch(req->type) {
case LAST_REQUEST_TYPE_SUSPEND:
break;
case LAST_REQUEST_TYPE_NONE:
case LAST_REQUEST_TYPE_END:
case LAST_REQUEST_TYPE_BEGIN:
case LAST_REQUEST_TYPE_RESUME:
sprintf(str,"Resume after %s from %s:%u at %s:%u\n",type_names[req->type],req->file,req->line,file,line);
logstr();
break;
}
switch(cx->requestDepth) {
case 1:
default:
sprintf(str,"depth=%u at Suspend after %s from %s:%u at %s:%u\n",cx->requestDepth,type_names[req->type],req->file,req->line,file,line);
logstr();
break;
case 0:
break;
}
req->type=LAST_REQUEST_TYPE_RESUME;
req->file=file;
req->line=line;
JS_ResumeRequest(cx, rc);
pthread_mutex_unlock(&req_mutex);
}
#endif
#ifndef _JS_REQUEST_H_
#define _JS_REQUEST_H_
//#define DEBUG_JS_REQUESTS
#ifdef DEBUG_JS_REQUESTS
#ifdef __cplusplus
extern "C" {
#endif
void js_debug_beginrequest(JSContext *cx, const char *file, unsigned long line);
void js_debug_endrequest(JSContext *cx, const char *file, unsigned long line);
jsrefcount js_debug_suspendrequest(JSContext *cx, const char *file, unsigned long line);
void js_debug_resumerequest(JSContext *cx, jsrefcount rc, const char *file, unsigned long line);
#ifdef __cplusplus
}
#endif
#define JS_BEGINREQUEST(cx) js_debug_beginrequest(cx, __FILE__, __LINE__)
#define JS_ENDREQUEST(cx) js_debug_endrequest(cx, __FILE__, __LINE__)
#define JS_SUSPENDREQUEST(cx) js_debug_suspendrequest(cx, __FILE__, __LINE__)
#define JS_RESUMEREQUEST(cx, rf) js_debug_resumerequest(cx, rf, __FILE__, __LINE__)
#else
#define JS_BEGINREQUEST(cx) JS_BeginRequest(cx);
#define JS_ENDREQUEST(cx) JS_EndRequest(cx);
#define JS_SUSPENDREQUEST(cx) JS_SuspendRequest(cx);
#define JS_RESUMEREQUEST(cx, rf) JS_ResumeRequest(cx, rf);
#endif
#endif
......@@ -50,6 +50,7 @@ OBJS = $(MTOBJODIR)$(DIRSEP)ansiterm$(OFILE) \
$(MTOBJODIR)$(DIRSEP)js_msg_area$(OFILE)\
$(MTOBJODIR)$(DIRSEP)js_msgbase$(OFILE)\
$(MTOBJODIR)$(DIRSEP)js_queue$(OFILE)\
$(MTOBJODIR)$(DIRSEP)js_request$(OFILE)\
$(MTOBJODIR)$(DIRSEP)js_rtpool$(OFILE)\
$(MTOBJODIR)$(DIRSEP)js_server$(OFILE)\
$(MTOBJODIR)$(DIRSEP)js_socket$(OFILE)\
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment