|
|
3.15b
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __unix__
#define XP_UNIX
#else
#define XP_PC
#define XP_WIN
#endif
#define JS_THREADSAFE
#include <jsapi.h>
#include "threadwrap.h"
#include "js_request.h"
#ifdef DEBUG_JS_REQUESTS
#define DEBUG
#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 (%p)\n",type_names[req->type],req->file,req->line,file,line,req->cx);
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 (%p)\n",cx->requestDepth,type_names[req->type],req->file,req->line,file,line,req->cx);
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 (%p)\n",type_names[req->type],req->file,req->line,file,line,req->cx);
}
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 (%p)\n",type_names[req->type],req->file,req->line,file,line,req->cx);
logstr();
break;
}
switch(cx->requestDepth) {
case 0:
default:
sprintf(str,"depth=%u at End after %s from %s:%u at %s:%u (%p)\n",cx->requestDepth,type_names[req->type],req->file,req->line,file,line,req->cx);
logstr();
break;
case 1:
break;
}
req->type=LAST_REQUEST_TYPE_END;
req->file=file;
req->line=line;
JS_EndRequest(cx);
if(cx->requestDepth==0) {
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 -1;
}
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 (%p)\n",type_names[req->type],req->file,req->line,file,line,req->cx);
logstr();
break;
}
switch(cx->requestDepth) {
case 0:
default:
sprintf(str,"depth=%u at Suspend after %s from %s:%u at %s:%u (%p)\n",cx->requestDepth,type_names[req->type],req->file,req->line,file,line,req->cx);
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 (%p)\n",type_names[req->type],req->file,req->line,file,line,req->cx);
logstr();
break;
}
switch(cx->requestDepth) {
case 1:
default:
sprintf(str,"depth=%u at Suspend after %s from %s:%u at %s:%u (%p)\n",cx->requestDepth,type_names[req->type],req->file,req->line,file,line,req->cx);
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.