rev 251 - trunk/src

SVN User <[email protected]>
Newsgroups gmane.comp.lang.prothon.cvs
Message-ID <[email protected]>
Author: bcollins
Date: 2004-04-01 18:08:33 -0500 (Thu, 01 Apr 2004)
New Revision: 251

Added:
   trunk/src/main.c
Removed:
   trunk/src/amain.c
Modified:
   trunk/src/Makefile.in
   trunk/src/builtins.c
Log:
Move head of dll_builtins list to top of builtins.c. This means we don't
need the amain.c alphabetical listing for VC anymore, so rename that back
to main.c.


Modified: trunk/src/Makefile.in
===================================================================
--- trunk/src/Makefile.in	2004-04-01 23:06:03 UTC (rev 250)
+++ trunk/src/Makefile.in	2004-04-01 23:08:33 UTC (rev 251)
@@ -9,10 +9,14 @@
 
 TARGET=prothon
 
+# WARNING! The builtins.o object MUST come first, else your binary will be
+# broken! This is not a joke. Also, the object.o object must follow the
+# BUILTIN_MOD_OBJS in the OBJS list below. Doesn't matter where really, so
+# long as it is after the BUILTIN_MOD_OBJS, since it contains the key for
+# the end of the list.
 BUILTIN_MOD_OBJS = builtins.o
 
-# NOTE: amain.o must come before any builtins, and object.o must come after
-OBJS = amain.o $(BUILTIN_MOD_OBJS) object.o argproc.o clist.o lock.o \
+OBJS = main.o $(BUILTIN_MOD_OBJS) object.o argproc.o clist.o lock.o \
 	memory_mgr.o parser.o prmalloc.o sys.o interp.o parser_routines.o \
 	symbol.o thread.o getline.o console.o
 

Deleted: trunk/src/amain.c
===================================================================
--- trunk/src/amain.c	2004-04-01 23:06:03 UTC (rev 250)
+++ trunk/src/amain.c	2004-04-01 23:08:33 UTC (rev 251)
@@ -1,290 +0,0 @@
-/* ====================================================================
- * The Prothon License Agreement, Version 1.0
- *
- * Copyright (c) 2004 Mark C. Hahn <[email protected]>. All rights
- * reserved.
- *
- * 1. This LICENSE AGREEMENT is between Mark C. Hahn ("MCH"), and the
- * Individual or Organization ("Licensee") accessing and otherwise using
- * Prothon software in source or binary form and its associated
- * documentation.
- * 
- * 2. Subject to the terms and conditions of this License Agreement, MCH
- * hereby grants Licensee a nonexclusive, royalty-free, world-wide license
- * to reproduce, analyze, test, perform and/or display publicly, prepare
- * derivative works, distribute, and otherwise use Prothon alone or in any
- * derivative version, provided, however, that MCH's License Agreement and
- * MCH's notice of copyright, i.e., "Copyright (c) 2004 Mark C. Hahn; All
- * Rights Reserved" are retained in Prothon alone or in any derivative
- * version prepared by Licensee.
- * 
- * 3. In the event Licensee prepares a derivative work that is based on or
- * incorporates Prothon or any part thereof, and wants to make the
- * derivative work available to others as provided herein, then Licensee
- * hereby agrees to include in any such work a brief summary of the
- * changes made to Prothon.
- * 
- * 4. MCH is making Prothon available to Licensee on an "AS IS" basis.
- * MCH MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.  BY WAY
- * OF EXAMPLE, BUT NOT LIMITATION, MCH MAKES NO AND DISCLAIMS ANY
- * REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY
- * PARTICULAR PURPOSE OR THAT THE USE OF PROTHON WILL NOT INFRINGE ANY
- * THIRD PARTY RIGHTS.
- * 
- * 5. MCH SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PROTHON
- * FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A
- * RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PROTHON, OR ANY
- * DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
- * 
- * 6. This License Agreement will automatically terminate upon a material
- * breach of its terms and conditions.
- * 
- * 7. Nothing in this License Agreement shall be deemed to create any
- * relationship of agency, partnership, or joint venture between MCH and
- * Licensee.  This License Agreement does not grant permission to use MCH
- * trademarks or trade name in a trademark sense to endorse or promote
- * products or services of Licensee, or any third party.
- * 
- * 8. By copying, installing or otherwise using Prothon, Licensee agrees
- * to be bound by the terms and conditions of this License Agreement.
- * ====================================================================
- */
-
-
-// main.c
-
-// #define TIMEIT
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "object.h"
-#include <prothon/prothon_dll.h>
-#include "memory_mgr.h"
-#include "parser.h"
-#include "interp.h"
-
-#include <apr_time.h>
-#include <apr_pools.h>
-#include <apr_thread_proc.h>
-#include <apr_portable.h>
-
-#define MEMMGR_TIMEOUT	(200/PAUSE_MS)  /* 200 ms */
-
-extern int yydebug;
-
-PR_PLACE_IN_SECTION(dll_initcall_t,start_dll_entry_ptr, "._module_init") = 0;
-
-static apr_pool_t *apr_root_pool = NULL;
-
-//**************************** get_pr_head_pool *******************************
-apr_pool_t* get_pr_head_pool(void) {
-	if (!apr_root_pool) {
-		printf("get_pr_head_pool error: called with no pool\n");
-		pr_exit(1);
-	}
-	return apr_root_pool;
-}
-
-static obj_p new_thread_object;
-static clist_p thread_registry;
-static DECLARE_PR_LOCK(thread_registry_lock);
-
-//**************************** register_thread ********************************
-/* New threads must call this first thing, it will release the
- * thread_registry_lock so that other threads can start. 
- * Returns the matching thread object */
-obj_p register_thread(apr_thread_t *this_thread)
-{
-	obj_p res = new_thread_object;
-	pr_thread_p thread_ptr    = res->data.ptr;
-	thread_ptr->apr_os_thread = apr_os_thread_current();
-	thread_ptr->apr_thread    = this_thread;
-	clist_append(thread_registry, res);
-	thread_ptr->running		  = TRUE;
-	pr_unlock(&thread_registry_lock);
-	return res;
-}
-
-static apr_threadattr_t *thread_attr = NULL;
-static apr_pool_t *thread_pool = NULL;
-
-//********************************* new_thread_obj ****************************
-obj_p new_thread_obj(apr_thread_start_t thread_func, void *thread_data)
-{
-	apr_status_t aprerr;
-	apr_thread_t *new_thread = NULL;
-	char buf[1024];
-
-	if (!thread_pool) {
-		if ((aprerr = apr_pool_create(&thread_pool, get_pr_head_pool())) != APR_SUCCESS) {
-			printf("Main error: apr_pool_create: %s\n",
-				apr_strerror(aprerr, buf, sizeof(buf)));
-			pr_exit(1);
-		}
-	}
-
-	if (!thread_attr) {
-		if ((aprerr = apr_threadattr_create(&thread_attr, thread_pool)) != APR_SUCCESS ||
-		    (aprerr = apr_threadattr_detach_set(thread_attr, 1)) != APR_SUCCESS) {
-			printf("Main error: apr_threadattr: %s\n",
-				apr_strerror(aprerr, buf, sizeof(buf)));
-			pr_exit(1);
-		}
-	}
-
-	/* Lock this, so we don't start a new thread, until the last one
-	 * calls register_thread(). */
-	pr_lock(&thread_registry_lock);
-
-	new_thread_object = new_object(OBJ(THREAD_PROTO));
-	new_thread_object->data_type = OBJ_TYPE_DATAPTR;
-	new_thread_object->data.ptr  = pr_malloc(sizeof(pr_thread_t));
-	memset(new_thread_object->data.ptr, 0, sizeof(pr_thread_t));
-
-	if ( ( aprerr = apr_thread_create( &new_thread, thread_attr, thread_func,
-					            thread_data, thread_pool ) ) != APR_SUCCESS ) {
-		printf("Main error: apr_thread_create: %s\n",
-			apr_strerror(aprerr, buf, sizeof(buf)));
-		pr_exit(1);
-	}
-	return new_thread_object;
-}
-
-//********************************* os_thread_2_apr ***************************
-apr_thread_t* os_thread_2_apr(apr_os_thread_t os_thread) {
-	int i;
-	apr_thread_t *res = NULL;
-
-	pr_lock(&thread_registry_lock);
-	for (i = 0; i < clist_len(thread_registry); i++) {
-		obj_p thread_obj = clist_item(thread_registry, i);
-		pr_thread_p thread_ptr = thread_obj->data.ptr;
-		if (thread_ptr->apr_os_thread == os_thread) {
-			res = thread_ptr->apr_thread;
-			break;
-		}
-	}
-	pr_unlock(&thread_registry_lock);
-
-	return res;
-}
-
-//********************************* main **************************************
-int main(int argc, char *argv[]) {
-	obj_p sys_argv_obj, main_argv_obj, threads, code_str_obj, main1_thread_obj;
-	pr_thread_p main1_thread_ptr = NULL;
-	isp ist;
-	apr_status_t aprerr;
-	char buf[1024];
-	int cmd_line_option_i_flg, mem_mgr_count;
-
-#ifdef DEBUG_THREADS
-	int torture_scan_num_ptr[]={1,2,3,4,5};
-	apr_thread_t *torture_thrd;
-	extern int torture_scan_thread_count;
-	extern void *torture_scan_thread(apr_thread_t *handle, void* thread_number_ptr);
-#endif
-
-	if ((aprerr = apr_app_initialize(&argc, (char const * const **)&argv, NULL))) {
-		char buf[1024];
-		printf("APR init error: %s\n", apr_strerror(aprerr, buf, 1024));
-		pr_exit(1);
-	}
-	atexit(&apr_terminate);
-
-	thread_registry = new_clist(5);
-
-	if ((aprerr = apr_pool_create(&apr_root_pool, NULL)))  {
-		printf("Main error: apr_pool_create: %s\n",
-		       apr_strerror(aprerr, buf, sizeof(buf)));
-		pr_exit(1);
-	}
-
-	/* Now that apr is ready, on to our stuff */
-	ist = get_ist();
-
-	yydebug = 0;
-
-#ifdef TRACE_PARSER
-	yydebug = 1;
-#endif
-
-	object_store_init(ist, 20);
-
-	sys_argv_obj = arginit(ist, argc, argv);
-	sysinit(ist, argv[0], sys_argv_obj);
-
-	if ((code_str_obj = get_attr(ist, sys_argv_obj, sym(ist, "code")))) {
-		exec_string(ist, strch(code_str_obj), FALSE, NULL);
-		check_exceptions(ist);
-	}
-	cmd_line_option_i_flg = (int)(intptr_t) get_attr(ist, sys_argv_obj, sym(ist, "i"));
-
-	main_argv_obj = get_attr(ist, sys_argv_obj, sym(ist, "argv"));
-	if (main_argv_obj && list_len(ist, main_argv_obj)) {
-		main1_thread_obj = new_thread_obj((apr_thread_start_t)main_thread, main_argv_obj);
-		main1_thread_ptr = main1_thread_obj->data.ptr;
-	}
-
-	threads = get_attr(ist, sys_argv_obj, sym(ist, "threads"));
-	if (threads) {
-		int i;
-		for (i = 0; i < list_len(ist, threads); i++)
-			new_thread_obj((apr_thread_start_t)main_thread, list_item(ist, threads, i));
-	}
-
-	new_thread_obj((apr_thread_start_t)mem_mgr_thread, NULL);
-
-#ifdef DEBUG_THREADS
-	SetThreadName("main");
-	new_thread_obj((apr_thread_start_t)torture_scan_thread, torture_scan_num_ptr);
-#endif
-
-#ifdef DEBUG_THREADS
-	printf("All threads started, now waiting for mains to finish...\n");
-#endif
-
-	/* Grab this lock, so we know all threads are started */
-	pr_lock(&thread_registry_lock); pr_unlock(&thread_registry_lock);
-
-	if (!main_threads_started) 
-		console(ist);
-	else {
-		while(main_threads_running) {
-			apr_sleep(PAUSE_MS*1000);
-			if (cmd_line_option_i_flg && (!main1_thread_ptr || !main1_thread_ptr->running)) {
-				console(ist);
-				cmd_line_option_i_flg = FALSE;
-			}
-		}
-		if (cmd_line_option_i_flg)
-			console(ist);
-	}
-
-#ifdef DEBUG_THREADS
-	printf("All main threads have terminated, now stopping memory manager ...\n");
-#endif
-
-	mem_mgr_req_termination = TRUE;
-	mem_mgr_count = 0;
-	while(!mem_mgr_terminated && ++mem_mgr_count < MEMMGR_TIMEOUT) apr_sleep(PAUSE_MS*1000);
-
-#ifdef DEBUG_THREADS
-	printf("Memory manager terminated, now stopping torture threads ...\n");
-	*torture_scan_num_ptr = 0;
-	while(torture_scan_thread_count) apr_sleep(PAUSE_MS*1000);
-	printf("All torture threads terminated, shutting down\n");
-#endif
-	
-#ifdef DUMP_OBJECTS_AT_END
-	dump(ist, "object-dump.txt", OBJ(ROOT_GLOBALS));
-#endif
-
-	return 0;
-}
-
-// common exit point for debug breakpoints
-void pr_exit(int n){
-	exit(n);
-}

Modified: trunk/src/builtins.c
===================================================================
--- trunk/src/builtins.c	2004-04-01 23:06:03 UTC (rev 250)
+++ trunk/src/builtins.c	2004-04-01 23:08:33 UTC (rev 251)
@@ -64,6 +64,12 @@
 #include "object.h"
 #include <prothon/prothon_dll.h>
 
+/* Leave this here. Do not move it, and do not declare anything above it.
+ * This is here for a reason, so that the builtin's can be loaded (this is
+ * the key for the start of the pointers to the functions for all the
+ * builtins). */
+PR_PLACE_IN_SECTION(dll_initcall_t,start_dll_entry_ptr, "._module_init") = 0;
+
 MODULE_DECLARE(Object);
 MODULE_DECLARE(False);
 MODULE_DECLARE(True);

Copied: trunk/src/main.c (from rev 249, trunk/src/amain.c)
===================================================================
--- trunk/src/amain.c	2004-04-01 18:45:21 UTC (rev 249)
+++ trunk/src/main.c	2004-04-01 23:08:33 UTC (rev 251)
@@ -0,0 +1,288 @@
+/* ====================================================================
+ * The Prothon License Agreement, Version 1.0
+ *
+ * Copyright (c) 2004 Mark C. Hahn <[email protected]>. All rights
+ * reserved.
+ *
+ * 1. This LICENSE AGREEMENT is between Mark C. Hahn ("MCH"), and the
+ * Individual or Organization ("Licensee") accessing and otherwise using
+ * Prothon software in source or binary form and its associated
+ * documentation.
+ * 
+ * 2. Subject to the terms and conditions of this License Agreement, MCH
+ * hereby grants Licensee a nonexclusive, royalty-free, world-wide license
+ * to reproduce, analyze, test, perform and/or display publicly, prepare
+ * derivative works, distribute, and otherwise use Prothon alone or in any
+ * derivative version, provided, however, that MCH's License Agreement and
+ * MCH's notice of copyright, i.e., "Copyright (c) 2004 Mark C. Hahn; All
+ * Rights Reserved" are retained in Prothon alone or in any derivative
+ * version prepared by Licensee.
+ * 
+ * 3. In the event Licensee prepares a derivative work that is based on or
+ * incorporates Prothon or any part thereof, and wants to make the
+ * derivative work available to others as provided herein, then Licensee
+ * hereby agrees to include in any such work a brief summary of the
+ * changes made to Prothon.
+ * 
+ * 4. MCH is making Prothon available to Licensee on an "AS IS" basis.
+ * MCH MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.  BY WAY
+ * OF EXAMPLE, BUT NOT LIMITATION, MCH MAKES NO AND DISCLAIMS ANY
+ * REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY
+ * PARTICULAR PURPOSE OR THAT THE USE OF PROTHON WILL NOT INFRINGE ANY
+ * THIRD PARTY RIGHTS.
+ * 
+ * 5. MCH SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PROTHON
+ * FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A
+ * RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PROTHON, OR ANY
+ * DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+ * 
+ * 6. This License Agreement will automatically terminate upon a material
+ * breach of its terms and conditions.
+ * 
+ * 7. Nothing in this License Agreement shall be deemed to create any
+ * relationship of agency, partnership, or joint venture between MCH and
+ * Licensee.  This License Agreement does not grant permission to use MCH
+ * trademarks or trade name in a trademark sense to endorse or promote
+ * products or services of Licensee, or any third party.
+ * 
+ * 8. By copying, installing or otherwise using Prothon, Licensee agrees
+ * to be bound by the terms and conditions of this License Agreement.
+ * ====================================================================
+ */
+
+
+// main.c
+
+// #define TIMEIT
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "object.h"
+#include <prothon/prothon_dll.h>
+#include "memory_mgr.h"
+#include "parser.h"
+#include "interp.h"
+
+#include <apr_time.h>
+#include <apr_pools.h>
+#include <apr_thread_proc.h>
+#include <apr_portable.h>
+
+#define MEMMGR_TIMEOUT	(200/PAUSE_MS)  /* 200 ms */
+
+extern int yydebug;
+
+static apr_pool_t *apr_root_pool = NULL;
+
+//**************************** get_pr_head_pool *******************************
+apr_pool_t* get_pr_head_pool(void) {
+	if (!apr_root_pool) {
+		printf("get_pr_head_pool error: called with no pool\n");
+		pr_exit(1);
+	}
+	return apr_root_pool;
+}
+
+static obj_p new_thread_object;
+static clist_p thread_registry;
+static DECLARE_PR_LOCK(thread_registry_lock);
+
+//**************************** register_thread ********************************
+/* New threads must call this first thing, it will release the
+ * thread_registry_lock so that other threads can start. 
+ * Returns the matching thread object */
+obj_p register_thread(apr_thread_t *this_thread)
+{
+	obj_p res = new_thread_object;
+	pr_thread_p thread_ptr    = res->data.ptr;
+	thread_ptr->apr_os_thread = apr_os_thread_current();
+	thread_ptr->apr_thread    = this_thread;
+	clist_append(thread_registry, res);
+	thread_ptr->running		  = TRUE;
+	pr_unlock(&thread_registry_lock);
+	return res;
+}
+
+static apr_threadattr_t *thread_attr = NULL;
+static apr_pool_t *thread_pool = NULL;
+
+//********************************* new_thread_obj ****************************
+obj_p new_thread_obj(apr_thread_start_t thread_func, void *thread_data)
+{
+	apr_status_t aprerr;
+	apr_thread_t *new_thread = NULL;
+	char buf[1024];
+
+	if (!thread_pool) {
+		if ((aprerr = apr_pool_create(&thread_pool, get_pr_head_pool())) != APR_SUCCESS) {
+			printf("Main error: apr_pool_create: %s\n",
+				apr_strerror(aprerr, buf, sizeof(buf)));
+			pr_exit(1);
+		}
+	}
+
+	if (!thread_attr) {
+		if ((aprerr = apr_threadattr_create(&thread_attr, thread_pool)) != APR_SUCCESS ||
+		    (aprerr = apr_threadattr_detach_set(thread_attr, 1)) != APR_SUCCESS) {
+			printf("Main error: apr_threadattr: %s\n",
+				apr_strerror(aprerr, buf, sizeof(buf)));
+			pr_exit(1);
+		}
+	}
+
+	/* Lock this, so we don't start a new thread, until the last one
+	 * calls register_thread(). */
+	pr_lock(&thread_registry_lock);
+
+	new_thread_object = new_object(OBJ(THREAD_PROTO));
+	new_thread_object->data_type = OBJ_TYPE_DATAPTR;
+	new_thread_object->data.ptr  = pr_malloc(sizeof(pr_thread_t));
+	memset(new_thread_object->data.ptr, 0, sizeof(pr_thread_t));
+
+	if ( ( aprerr = apr_thread_create( &new_thread, thread_attr, thread_func,
+					            thread_data, thread_pool ) ) != APR_SUCCESS ) {
+		printf("Main error: apr_thread_create: %s\n",
+			apr_strerror(aprerr, buf, sizeof(buf)));
+		pr_exit(1);
+	}
+	return new_thread_object;
+}
+
+//********************************* os_thread_2_apr ***************************
+apr_thread_t* os_thread_2_apr(apr_os_thread_t os_thread) {
+	int i;
+	apr_thread_t *res = NULL;
+
+	pr_lock(&thread_registry_lock);
+	for (i = 0; i < clist_len(thread_registry); i++) {
+		obj_p thread_obj = clist_item(thread_registry, i);
+		pr_thread_p thread_ptr = thread_obj->data.ptr;
+		if (thread_ptr->apr_os_thread == os_thread) {
+			res = thread_ptr->apr_thread;
+			break;
+		}
+	}
+	pr_unlock(&thread_registry_lock);
+
+	return res;
+}
+
+//********************************* main **************************************
+int main(int argc, char *argv[]) {
+	obj_p sys_argv_obj, main_argv_obj, threads, code_str_obj, main1_thread_obj;
+	pr_thread_p main1_thread_ptr = NULL;
+	isp ist;
+	apr_status_t aprerr;
+	char buf[1024];
+	int cmd_line_option_i_flg, mem_mgr_count;
+
+#ifdef DEBUG_THREADS
+	int torture_scan_num_ptr[]={1,2,3,4,5};
+	apr_thread_t *torture_thrd;
+	extern int torture_scan_thread_count;
+	extern void *torture_scan_thread(apr_thread_t *handle, void* thread_number_ptr);
+#endif
+
+	if ((aprerr = apr_app_initialize(&argc, (char const * const **)&argv, NULL))) {
+		char buf[1024];
+		printf("APR init error: %s\n", apr_strerror(aprerr, buf, 1024));
+		pr_exit(1);
+	}
+	atexit(&apr_terminate);
+
+	thread_registry = new_clist(5);
+
+	if ((aprerr = apr_pool_create(&apr_root_pool, NULL)))  {
+		printf("Main error: apr_pool_create: %s\n",
+		       apr_strerror(aprerr, buf, sizeof(buf)));
+		pr_exit(1);
+	}
+
+	/* Now that apr is ready, on to our stuff */
+	ist = get_ist();
+
+	yydebug = 0;
+
+#ifdef TRACE_PARSER
+	yydebug = 1;
+#endif
+
+	object_store_init(ist, 20);
+
+	sys_argv_obj = arginit(ist, argc, argv);
+	sysinit(ist, argv[0], sys_argv_obj);
+
+	if ((code_str_obj = get_attr(ist, sys_argv_obj, sym(ist, "code")))) {
+		exec_string(ist, strch(code_str_obj), FALSE, NULL);
+		check_exceptions(ist);
+	}
+	cmd_line_option_i_flg = (int)(intptr_t) get_attr(ist, sys_argv_obj, sym(ist, "i"));
+
+	main_argv_obj = get_attr(ist, sys_argv_obj, sym(ist, "argv"));
+	if (main_argv_obj && list_len(ist, main_argv_obj)) {
+		main1_thread_obj = new_thread_obj((apr_thread_start_t)main_thread, main_argv_obj);
+		main1_thread_ptr = main1_thread_obj->data.ptr;
+	}
+
+	threads = get_attr(ist, sys_argv_obj, sym(ist, "threads"));
+	if (threads) {
+		int i;
+		for (i = 0; i < list_len(ist, threads); i++)
+			new_thread_obj((apr_thread_start_t)main_thread, list_item(ist, threads, i));
+	}
+
+	new_thread_obj((apr_thread_start_t)mem_mgr_thread, NULL);
+
+#ifdef DEBUG_THREADS
+	SetThreadName("main");
+	new_thread_obj((apr_thread_start_t)torture_scan_thread, torture_scan_num_ptr);
+#endif
+
+#ifdef DEBUG_THREADS
+	printf("All threads started, now waiting for mains to finish...\n");
+#endif
+
+	/* Grab this lock, so we know all threads are started */
+	pr_lock(&thread_registry_lock); pr_unlock(&thread_registry_lock);
+
+	if (!main_threads_started) 
+		console(ist);
+	else {
+		while(main_threads_running) {
+			apr_sleep(PAUSE_MS*1000);
+			if (cmd_line_option_i_flg && (!main1_thread_ptr || !main1_thread_ptr->running)) {
+				console(ist);
+				cmd_line_option_i_flg = FALSE;
+			}
+		}
+		if (cmd_line_option_i_flg)
+			console(ist);
+	}
+
+#ifdef DEBUG_THREADS
+	printf("All main threads have terminated, now stopping memory manager ...\n");
+#endif
+
+	mem_mgr_req_termination = TRUE;
+	mem_mgr_count = 0;
+	while(!mem_mgr_terminated && ++mem_mgr_count < MEMMGR_TIMEOUT) apr_sleep(PAUSE_MS*1000);
+
+#ifdef DEBUG_THREADS
+	printf("Memory manager terminated, now stopping torture threads ...\n");
+	*torture_scan_num_ptr = 0;
+	while(torture_scan_thread_count) apr_sleep(PAUSE_MS*1000);
+	printf("All torture threads terminated, shutting down\n");
+#endif
+	
+#ifdef DUMP_OBJECTS_AT_END
+	dump(ist, "object-dump.txt", OBJ(ROOT_GLOBALS));
+#endif
+
+	return 0;
+}
+
+// common exit point for debug breakpoints
+void pr_exit(int n){
+	exit(n);
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.