|
|
1.1 root 1: #include <stdio.h>
2: #include <stdlib.h>
3: #include <string.h>
4:
5: #ifdef __unix__
6: #define XP_UNIX
7: #else
8: #define XP_PC
9: #define XP_WIN
10: #endif
11:
12: #define JS_THREADSAFE
13: #include <jsapi.h>
14: #include "threadwrap.h"
15: #include "js_request.h"
16:
17: #ifdef DEBUG_JS_REQUESTS
18:
19: #define DEBUG
20: #include <jscntxt.h>
21:
22: enum last_request_type {
23: LAST_REQUEST_TYPE_NONE
24: ,LAST_REQUEST_TYPE_BEGIN
25: ,LAST_REQUEST_TYPE_END
26: ,LAST_REQUEST_TYPE_SUSPEND
27: ,LAST_REQUEST_TYPE_RESUME
28: };
29: static const char *type_names[5]={"None", "BeginRequest", "EndRequest", "SuspendRequest", "ResumeRequest"};
30:
31: struct request_log {
32: JSContext* cx;
33: enum last_request_type type;
34: const char* file;
35: unsigned long line;
36: struct request_log* next;
37: struct request_log* prev;
38: };
39:
40: static struct request_log* first_request;
41: static int initialized=0;
42: static pthread_mutex_t req_mutex;
43: static char str[1024];
44:
45: static void logstr(void)
46: {
47: FILE *f;
48:
49: if((f=fopen("../data/logs/JS_RequestErrors.log", "a"))!=NULL) {
50: fputs(str, f);
51: fclose(f);
52: }
53: else {
54: fputs(str, stderr);
55: }
56: }
57:
58: static struct request_log *match_request(JSContext *cx)
59: {
60: struct request_log *ent;
61:
62: for(ent=first_request; ent != NULL; ent=ent->next) {
63: if(ent->cx==cx)
64: return(ent);
65: }
66:
67: ent=malloc(sizeof(struct request_log));
68: if(ent != NULL) {
69: memset(ent, 0, sizeof(struct request_log));
70: ent->cx=cx;
71: ent->type=LAST_REQUEST_TYPE_NONE;
72: ent->prev=NULL;
73: ent->next=first_request;
74: if(first_request != NULL) {
75: first_request->prev=ent;
76: }
77: first_request=ent;
78: return(ent);
79: }
80: return(NULL);
81: }
82:
83: static void initialize_request(void)
84: {
85: pthread_mutex_init(&req_mutex, NULL);
86: initialized=1;
87: }
88:
89: void js_debug_beginrequest(JSContext *cx, const char *file, unsigned long line)
90: {
91: struct request_log *req;
92:
93: if(!initialized)
94: initialize_request();
95: pthread_mutex_lock(&req_mutex);
96: req=match_request(cx);
97: if(req==NULL) {
98: strcpy(str,"Missing req in Begin\n");
99: logstr();
100: return;
101: }
102: switch(req->type) {
103: case LAST_REQUEST_TYPE_NONE:
104: case LAST_REQUEST_TYPE_END:
105: break;
106: case LAST_REQUEST_TYPE_BEGIN:
107: case LAST_REQUEST_TYPE_SUSPEND:
108: case LAST_REQUEST_TYPE_RESUME:
109: 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);
110: logstr();
111: break;
112: }
113: switch(cx->requestDepth) {
114: case 0:
115: break;
116: case 1:
117: default:
118: 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);
119: logstr();
120: break;
121: }
122:
123: req->type=LAST_REQUEST_TYPE_BEGIN;
124: req->file=file;
125: req->line=line;
126: JS_BeginRequest(cx);
127: pthread_mutex_unlock(&req_mutex);
128: }
129:
130: void js_debug_endrequest(JSContext *cx, const char *file, unsigned long line)
131: {
132: struct request_log *req;
133:
134: if(!initialized)
135: initialize_request();
136: pthread_mutex_lock(&req_mutex);
137: req=match_request(cx);
138: if(req==NULL) {
139: strcpy(str,"Missing req in End\n");
140: logstr();
141: return;
142: }
143: switch(req->type) {
144: case LAST_REQUEST_TYPE_BEGIN:
145: if(req->file) {
146: if(strcmp(req->file, file) != 0 || line < req->line) {
147: 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);
148: }
149: break;
150: }
151: case LAST_REQUEST_TYPE_RESUME:
152: break;
153: case LAST_REQUEST_TYPE_NONE:
154: case LAST_REQUEST_TYPE_END:
155: case LAST_REQUEST_TYPE_SUSPEND:
156: 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);
157: logstr();
158: break;
159: }
160: switch(cx->requestDepth) {
161: case 0:
162: default:
163: 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);
164: logstr();
165: break;
166: case 1:
167: break;
168: }
169:
170: req->type=LAST_REQUEST_TYPE_END;
171: req->file=file;
172: req->line=line;
173: JS_EndRequest(cx);
174: if(cx->requestDepth==0) {
175: if(req->prev != NULL)
176: req->prev->next=req->next;
177: if(req->next != NULL)
178: req->next->prev=req->prev;
179: if(first_request==req) {
180: if(req->prev != NULL)
181: first_request=req->prev;
182: else
183: first_request=req->next;
184: }
185: free(req);
186: }
187: pthread_mutex_unlock(&req_mutex);
188: }
189:
190: jsrefcount js_debug_suspendrequest(JSContext *cx, const char *file, unsigned long line)
191: {
192: struct request_log *req;
193: jsrefcount ret;
194:
195: if(!initialized)
196: initialize_request();
197: pthread_mutex_lock(&req_mutex);
198: req=match_request(cx);
199: if(req==NULL) {
200: strcpy(str,"Missing req in Suspend\n");
201: logstr();
202: return -1;
203: }
204: switch(req->type) {
205: case LAST_REQUEST_TYPE_BEGIN:
206: case LAST_REQUEST_TYPE_RESUME:
207: break;
208: case LAST_REQUEST_TYPE_NONE:
209: if(req->file==NULL) /* Assumed to be a provided request */
210: break;
211: case LAST_REQUEST_TYPE_END:
212: case LAST_REQUEST_TYPE_SUSPEND:
213: 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);
214: logstr();
215: break;
216: }
217: switch(cx->requestDepth) {
218: case 0:
219: default:
220: 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);
221: logstr();
222: break;
223: case 1:
224: break;
225: }
226:
227: req->type=LAST_REQUEST_TYPE_SUSPEND;
228: req->file=file;
229: req->line=line;
230: ret=JS_SuspendRequest(cx);
231: pthread_mutex_unlock(&req_mutex);
232: return(ret);
233: }
234:
235: void js_debug_resumerequest(JSContext *cx, jsrefcount rc, const char *file, unsigned long line)
236: {
237: struct request_log *req;
238:
239: if(!initialized)
240: initialize_request();
241: pthread_mutex_lock(&req_mutex);
242: req=match_request(cx);
243: if(req==NULL) {
244: strcpy(str,"Missing req in Resume\n");
245: logstr();
246: return;
247: }
248: switch(req->type) {
249: case LAST_REQUEST_TYPE_SUSPEND:
250: break;
251: case LAST_REQUEST_TYPE_NONE:
252: case LAST_REQUEST_TYPE_END:
253: case LAST_REQUEST_TYPE_BEGIN:
254: case LAST_REQUEST_TYPE_RESUME:
255: 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);
256: logstr();
257: break;
258: }
259: switch(cx->requestDepth) {
260: case 1:
261: default:
262: 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);
263: logstr();
264: break;
265: case 0:
266: break;
267: }
268:
269: req->type=LAST_REQUEST_TYPE_RESUME;
270: req->file=file;
271: req->line=line;
272: JS_ResumeRequest(cx, rc);
273: pthread_mutex_unlock(&req_mutex);
274: }
275:
276: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.