From fc656d6b3bd80ae49edf03e16aa903382a331e87 Mon Sep 17 00:00:00 2001
From: deuce <>
Date: Thu, 4 Dec 2008 19:45:28 +0000
Subject: [PATCH] Use a pool of JSRuntimes to avoid the 128 threads with
 runtime issue with SpiderMonkey 1.7

---
 src/sbbs3/ftpsrvr.c   |  5 +++--
 src/sbbs3/js_global.c |  5 +++--
 src/sbbs3/js_rtpool.c | 47 +++++++++++++++++++++++++++++++++++++++++++
 src/sbbs3/js_rtpool.h | 45 +++++++++++++++++++++++++++++++++++++++++
 src/sbbs3/jsexec.c    |  5 +++--
 src/sbbs3/mailsrvr.c  |  5 +++--
 src/sbbs3/main.cpp    |  5 +++--
 src/sbbs3/objects.mk  |  1 +
 src/sbbs3/services.c  |  9 +++++----
 src/sbbs3/websrvr.c   |  9 +++++----
 10 files changed, 118 insertions(+), 18 deletions(-)
 create mode 100644 src/sbbs3/js_rtpool.c
 create mode 100644 src/sbbs3/js_rtpool.h

diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c
index d740f231dd..3da30c8eb8 100644
--- a/src/sbbs3/ftpsrvr.c
+++ b/src/sbbs3/ftpsrvr.c
@@ -51,6 +51,7 @@
 #include "text.h"			/* TOTAL_TEXT */
 #include "ftpsrvr.h"
 #include "telnet.h"
+#include "js_rtpool.h"
 
 /* Constants */
 
@@ -3858,7 +3859,7 @@ static void ctrl_thread(void* arg)
 						lprintf(LOG_DEBUG,"%04d JavaScript: Creating runtime: %lu bytes"
 							,sock,startup->js.max_bytes);
 
-						if((js_runtime = JS_NewRuntime(startup->js.max_bytes))==NULL) {
+						if((js_runtime = jsrt_GetNew(startup->js.max_bytes))==NULL) {
 							lprintf(LOG_ERR,"%04d !ERROR creating JavaScript runtime",sock);
 							sockprintf(sock,"451 Error creating JavaScript runtime");
 							filepos=0;
@@ -4462,7 +4463,7 @@ static void ctrl_thread(void* arg)
 
 	if(js_runtime!=NULL) {
 		lprintf(LOG_DEBUG,"%04d JavaScript: Destroying runtime",sock);
-		JS_DestroyRuntime(js_runtime);
+		jsrt_Release(js_runtime);
 	}
 
 #endif
diff --git a/src/sbbs3/js_global.c b/src/sbbs3/js_global.c
index aafebba707..25eae3b3d0 100644
--- a/src/sbbs3/js_global.c
+++ b/src/sbbs3/js_global.c
@@ -42,6 +42,7 @@
 #include "base64.h"
 #include "htmlansi.h"
 #include "ini_file.h"
+#include "js_rtpool.h"
 
 /* SpiderMonkey: */
 #include <jsfun.h>
@@ -124,7 +125,7 @@ static void background_thread(void* arg)
 	js_enqueue_value(bg->cx, bg->msg_queue, result, NULL);
 	JS_DestroyScript(bg->cx, bg->script);
 	JS_DestroyContext(bg->cx);
-	JS_DestroyRuntime(bg->runtime);
+	jsrt_Release(bg->runtime);
 	free(bg);
 }
 
@@ -255,7 +256,7 @@ js_load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 		bg->branch.counter=0;
 		bg->branch.gc_attempts=0;
 
-		if((bg->runtime = JS_NewRuntime(JAVASCRIPT_MAX_BYTES))==NULL)
+		if((bg->runtime = jsrt_GetNew(JAVASCRIPT_MAX_BYTES))==NULL)
 			return(JS_FALSE);
 
 	    if((bg->cx = JS_NewContext(bg->runtime, JAVASCRIPT_CONTEXT_STACK))==NULL)
diff --git a/src/sbbs3/js_rtpool.c b/src/sbbs3/js_rtpool.c
new file mode 100644
index 0000000000..aafb646a54
--- /dev/null
+++ b/src/sbbs3/js_rtpool.c
@@ -0,0 +1,47 @@
+/* $Id$ */
+
+#include "js_rtpool.h"
+
+struct jsrt_queue {
+        JSRuntime       *rt;
+        int             maxbytes;
+	int		used;
+	int		created;
+};
+
+#define JSRT_QUEUE_SIZE		128
+struct jsrt_queue jsrt_queue[JSRT_QUEUE_SIZE];
+
+JSRuntime *jsrt_GetNew(int maxbytes)
+{
+	int	i;
+
+	for(i=0; i<JSRT_QUEUE_SIZE; i++) {
+		if(!jsrt_queue[i].created) {
+			jsrt_queue[i].rt=JS_NewRuntime(maxbytes);
+			if(jsrt_queue[i].rt != NULL) {
+				jsrt_queue[i].maxbytes=maxbytes;
+				jsrt_queue[i].created=1;
+				jsrt_queue[i].used=0;
+			}
+		}
+		if(jsrt_queue[i].created && jsrt_queue[i].maxbytes == maxbytes && jsrt_queue[i].used == 0) {
+			jsrt_queue[i].used=1;
+			return(jsrt_queue[i].rt);
+		}
+	}
+
+	return(NULL);
+}
+
+void jsrt_Release(JSRuntime *rt)
+{
+	int	i;
+
+	for(i=0; i<JSRT_QUEUE_SIZE; i++) {
+		if(rt==jsrt_queue[i].rt) {
+			jsrt_queue[i].used=0;
+			/* TODO: Clear "stuff"? */
+		}
+	}
+}
diff --git a/src/sbbs3/js_rtpool.h b/src/sbbs3/js_rtpool.h
new file mode 100644
index 0000000000..56b7edd999
--- /dev/null
+++ b/src/sbbs3/js_rtpool.h
@@ -0,0 +1,45 @@
+/* $Id$ */
+
+#ifndef _JS_RTPOOL_H_
+#define _JS_RTPOOL_H_
+
+#ifdef __unix__
+	#define XP_UNIX
+#else
+	#define XP_PC
+	#define XP_WIN
+#endif
+#include <jsapi.h>
+
+#ifdef DLLEXPORT
+#undef DLLEXPORT
+#endif
+#ifdef DLLCALL
+#undef DLLCALL
+#endif
+#ifdef _WIN32
+	#ifdef SBBS_EXPORTS
+		#define DLLEXPORT	__declspec(dllexport)
+	#else
+		#define DLLEXPORT	__declspec(dllimport)
+	#endif
+	#ifdef __BORLANDC__
+		#define DLLCALL __stdcall
+	#else
+		#define DLLCALL
+	#endif
+#else	/* !_WIN32 */
+	#define DLLEXPORT
+	#define DLLCALL
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+DLLEXPORT JSRuntime * DLLCALL jsrt_GetNew(int maxbytes);
+DLLEXPORT void DLLCALL jsrt_Release(JSRuntime *);
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/src/sbbs3/jsexec.c b/src/sbbs3/jsexec.c
index 552889f9db..0385f8658d 100644
--- a/src/sbbs3/jsexec.c
+++ b/src/sbbs3/jsexec.c
@@ -45,6 +45,7 @@
 
 #include "sbbs.h"
 #include "ciolib.h"
+#include "js_rtpool.h"
 
 #define DEFAULT_LOG_LEVEL	LOG_DEBUG	/* Display all LOG levels */
 #define DEFAULT_ERR_LOG_LVL	LOG_WARNING
@@ -570,7 +571,7 @@ static BOOL js_init(char** environ)
 	fprintf(statfp,"JavaScript: Creating runtime: %lu bytes\n"
 		,js_max_bytes);
 
-	if((js_runtime = JS_NewRuntime(js_max_bytes))==NULL)
+	if((js_runtime = jsrt_GetNew(js_max_bytes))==NULL)
 		return(FALSE);
 
 	fprintf(statfp,"JavaScript: Initializing context (stack: %lu bytes)\n"
@@ -1023,7 +1024,7 @@ int main(int argc, char **argv, char** environ)
 		fprintf(statfp,"JavaScript: Destroying context\n");
 		JS_DestroyContext(js_cx);
 		fprintf(statfp,"JavaScript: Destroying runtime\n");
-		JS_DestroyRuntime(js_runtime);	
+		jsrt_Release(js_runtime);	
 
 	} while((recycled || loop) && !terminated);
 
diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c
index 5bb693d971..7b41acfd52 100644
--- a/src/sbbs3/mailsrvr.c
+++ b/src/sbbs3/mailsrvr.c
@@ -56,6 +56,7 @@
 #include "ini_file.h"
 #include "netwrap.h"	/* getNameServerList() */
 #include "xpendian.h"
+#include "js_rtpool.h"
 
 /* Constants */
 #define FORWARD			"forward:"
@@ -1609,7 +1610,7 @@ js_mailproc(SOCKET sock, client_t* client, user_t* user
 		lprintf(LOG_DEBUG,"%04d JavaScript: Creating runtime: %lu bytes\n"
 			,sock, startup->js.max_bytes);
 
-		if((js_runtime = JS_NewRuntime(startup->js.max_bytes))==NULL)
+		if((js_runtime = jsrt_GetNew(startup->js.max_bytes))==NULL)
 			break;
 
 		lprintf(LOG_DEBUG,"%04d JavaScript: Initializing context (stack: %lu bytes)\n"
@@ -1718,7 +1719,7 @@ js_mailproc(SOCKET sock, client_t* client, user_t* user
 	if(js_cx!=NULL)
 		JS_DestroyContext(js_cx);
 	if(js_runtime!=NULL)
-		JS_DestroyRuntime(js_runtime);
+		jsrt_Release(js_runtime);
 
 	return(success);
 }
diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp
index 98ccf1e867..62de411898 100644
--- a/src/sbbs3/main.cpp
+++ b/src/sbbs3/main.cpp
@@ -39,6 +39,7 @@
 #include "ident.h"
 #include "telnet.h" 
 #include "netwrap.h"
+#include "js_rtpool.h"
 
 #ifdef __unix__
 	#include <sys/un.h>
@@ -980,7 +981,7 @@ bool sbbs_t::js_init(ulong* stack_frame)
 	lprintf(LOG_DEBUG,"%s JavaScript: Creating runtime: %lu bytes"
 		,node,startup->js.max_bytes);
 
-	if((js_runtime = JS_NewRuntime(startup->js.max_bytes))==NULL)
+	if((js_runtime = jsrt_GetNew(startup->js.max_bytes))==NULL)
 		return(false);
 
 	lprintf(LOG_DEBUG,"%s JavaScript: Initializing context (stack: %lu bytes)"
@@ -3186,7 +3187,7 @@ sbbs_t::~sbbs_t()
 
 	if(js_runtime!=NULL) {
 		lprintf(LOG_DEBUG,"%s JavaScript: Destroying runtime",node);
-		JS_DestroyRuntime(js_runtime);
+		jsrt_Release(js_runtime);
 		js_runtime=NULL;
 	}
 #endif
diff --git a/src/sbbs3/objects.mk b/src/sbbs3/objects.mk
index 65b6b7c0ee..ece9133980 100644
--- a/src/sbbs3/objects.mk
+++ b/src/sbbs3/objects.mk
@@ -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_rtpool$(OFILE)\
 			$(MTOBJODIR)$(DIRSEP)js_server$(OFILE)\
 			$(MTOBJODIR)$(DIRSEP)js_socket$(OFILE)\
 			$(MTOBJODIR)$(DIRSEP)js_sprintf$(OFILE)\
diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c
index 69ed74c6ed..964d8acbca 100644
--- a/src/sbbs3/services.c
+++ b/src/sbbs3/services.c
@@ -59,6 +59,7 @@
 #include "services.h"
 #include "ident.h"	/* identify() */
 #include "sbbs_ini.h"
+#include "js_rtpool.h"
 
 /* Constants */
 
@@ -1063,7 +1064,7 @@ static void js_service_thread(void* arg)
 	/* Initialize client display */
 	client_on(socket,&client,FALSE /* update */);
 
-	if((js_runtime=JS_NewRuntime(service->js.max_bytes))==NULL
+	if((js_runtime=jsrt_GetNew(service->js.max_bytes))==NULL
 		|| (js_cx=js_initcx(js_runtime,socket,&service_client,&js_glob))==NULL) {
 		lprintf(LOG_ERR,"%04d !%s ERROR initializing JavaScript context"
 			,socket,service->protocol);
@@ -1116,7 +1117,7 @@ static void js_service_thread(void* arg)
 	}
 	JS_DestroyContext(js_cx);	/* Free Context */
 
-	JS_DestroyRuntime(js_runtime);
+	jsrt_Release(js_runtime);
 
 	if(service_client.user.number) {
 		lprintf(LOG_INFO,"%04d %s Logging out %s"
@@ -1177,7 +1178,7 @@ static void js_static_service_thread(void* arg)
 	service_client.branch.terminated = &service->terminated;
 	service_client.branch.auto_terminate = TRUE;
 
-	if((js_runtime=JS_NewRuntime(service->js.max_bytes))==NULL) {
+	if((js_runtime=jsrt_GetNew(service->js.max_bytes))==NULL) {
 		lprintf(LOG_ERR,"%04d !%s ERROR initializing JavaScript runtime"
 			,service->socket,service->protocol);
 		close_socket(service->socket);
@@ -1222,7 +1223,7 @@ static void js_static_service_thread(void* arg)
 	if(js_cx!=NULL)
 		JS_DestroyContext(js_cx);	/* Free Context */
 
-	JS_DestroyRuntime(js_runtime);
+	jsrt_Release(js_runtime);
 
 	if(service->clients) {
 		lprintf(LOG_WARNING,"%04d %s !service terminating with %u active clients"
diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c
index 20708da7b2..23dd3ff63f 100644
--- a/src/sbbs3/websrvr.c
+++ b/src/sbbs3/websrvr.c
@@ -65,6 +65,7 @@
 #include "websrvr.h"
 #include "base64.h"
 #include "md5.h"
+#include "js_rtpool.h"
 
 static const char*	server_name="Synchronet Web Server";
 static const char*	newline="\r\n";
@@ -4394,7 +4395,7 @@ static BOOL js_setup(http_session_t* session)
 		lprintf(LOG_INFO,"%04d JavaScript: Creating runtime: %lu bytes"
 			,session->socket,startup->js.max_bytes);
 
-		if((session->js_runtime=JS_NewRuntime(startup->js.max_bytes))==NULL) {
+		if((session->js_runtime=jsrt_GetNew(startup->js.max_bytes))==NULL) {
 			lprintf(LOG_ERR,"%04d !ERROR creating JavaScript runtime",session->socket);
 			return(FALSE);
 		}
@@ -5005,7 +5006,7 @@ void http_session_thread(void* arg)
 #ifndef ONE_JS_RUNTIME
 	if(session.js_runtime!=NULL) {
 		lprintf(LOG_INFO,"%04d JavaScript: Destroying runtime",socket);
-		JS_DestroyRuntime(session.js_runtime);
+		jsrt_Release(session.js_runtime);
 		session.js_runtime=NULL;
 	}
 #endif
@@ -5462,7 +5463,7 @@ void DLLCALL web_server(void* arg)
     	    lprintf(LOG_INFO,"%04d JavaScript: Creating runtime: %lu bytes"
         	    ,server_socket,startup->js.max_bytes);
 
-    	    if((js_runtime=JS_NewRuntime(startup->js.max_bytes))==NULL) {
+    	    if((js_runtime=jsrt_GetNew(startup->js.max_bytes))==NULL) {
         	    lprintf(LOG_ERR,"%04d !ERROR creating JavaScript runtime",server_socket);
 				/* Sleep 15 seconds then try again */
 				/* ToDo: Something better should be used here. */
@@ -5685,7 +5686,7 @@ void DLLCALL web_server(void* arg)
 #ifdef ONE_JS_RUNTIME
     	if(js_runtime!=NULL) {
         	lprintf(LOG_INFO,"%04d JavaScript: Destroying runtime",server_socket);
-        	JS_DestroyRuntime(js_runtime);
+        	jsrt_Release(js_runtime);
     	    js_runtime=NULL;
 	    }
 #endif
-- 
GitLab