[Freeswitch-svn] [commit] r4338 - freeswitch/trunk/src

Freeswitch SVN mikej at freeswitch.org
Tue Feb 20 13:27:21 EST 2007


Author: mikej
Date: Tue Feb 20 13:27:21 2007
New Revision: 4338

Modified:
   freeswitch/trunk/src/switch_core.c

Log:
refactor switch_core_sql_thread with the following main changes:

Do the entire transaction as a single exec, instead of 3 separate ones to resolve issue of unmatched transaction error.
try really hard to commit the transaction (1000 times) but we no longer try forever.  If 1000 times fail, you will lose some update/insert/deletes from the core db, but we will no longer continue to loop forever and stop processing the sql queue in the case of an error.
added better overflow protection to the buffer, we now ignore sql strings we get over 64k. (not full transactions, just individual sql strings that we get queued).  Previously this caused a buffer overflow.
We now use sprintf instead of snprintf as we are already handling overflow checks outside of the sprintf.


Modified: freeswitch/trunk/src/switch_core.c
==============================================================================
--- freeswitch/trunk/src/switch_core.c	(original)
+++ freeswitch/trunk/src/switch_core.c	Tue Feb 20 13:27:21 2007
@@ -3790,9 +3790,15 @@
 	uint32_t itterations = 0;
 	uint8_t trans = 0, nothing_in_queue = 0;
 	uint32_t freq = 1000, target = 1000;
-	uint32_t len = 0;
-	uint32_t sql_len = SQLLEN;
+	switch_size_t len = 0, sql_len = SQLLEN;
+	const char *begin_sql = "BEGIN DEFERRED TRANSACTION CORE1;\n";
+	char *end_sql = "END TRANSACTION CORE1";
+	switch_size_t begin_len = strlen(begin_sql);
+	switch_size_t end_len = strlen(end_sql);
 	char *sqlbuf = (char *) malloc(sql_len);
+	char *sql;
+	switch_size_t newlen;
+
 	
 	if (!runtime.event_db) {
 		runtime.event_db = switch_core_db_handle();
@@ -3801,28 +3807,32 @@
 
 	for(;;) {
 		if (switch_queue_trypop(runtime.sql_queue, &pop) == SWITCH_STATUS_SUCCESS) {
-			char *sql = (char *) pop;
-			uint32_t newlen;
+			sql = (char *) pop;
 
 			if (sql) {
-				if (itterations == 0) {
-					char *isql = "begin transaction CORE1;\n";
-					switch_core_db_persistant_execute(runtime.event_db, isql, 0);
-					trans = 1;
-					
-				}
+				newlen = strlen(sql) + 2;
+
+				/* ignore abnormally large strings sql strings as potential buffer overflow */
+				if (newlen + end_len < SQLLEN) {
+
+					if (itterations == 0) {
+						len = begin_len;
+						sprintf(sqlbuf, "%s", begin_sql); 
+						trans = 1;
+					}
 
-				itterations++;
-				newlen = (uint32_t)strlen(sql) + 2;
-				if (len + newlen > sql_len) {
-					sql_len = len + SQLLEN;
-					if (!(sqlbuf = realloc(sqlbuf, sql_len))) {
-						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL thread ending on mem err\n");
-						break;
+					itterations++;
+					if (len + newlen + end_len > sql_len) {
+						sql_len = len + SQLLEN;
+						if (!(sqlbuf = realloc(sqlbuf, sql_len))) {
+							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL thread ending on mem err\n");
+							break;
+						}
 					}
+					sprintf(sqlbuf + len, "%s;\n", sql); 
+					len += newlen;
+
 				}
-				snprintf(sqlbuf + len, sql_len - len, "%s;\n", sql); 
-				len += newlen;
 				switch_core_db_free(sql);
 			} else {
 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "SQL thread ending\n");
@@ -3834,10 +3844,10 @@
 
 
 		if (trans && ((itterations == target) || nothing_in_queue)) {
-			char *isql = "end transaction CORE1";
-
-			switch_core_db_persistant_execute(runtime.event_db, sqlbuf, 0);
-			switch_core_db_persistant_execute(runtime.event_db, isql, 0);
+			sprintf(sqlbuf + len, "%s", end_sql); 
+			if (switch_core_db_persistant_execute(runtime.event_db, sqlbuf, 1000) != SWITCH_STATUS_SUCCESS) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL thread unable to commit transaction, records lost!\n");
+			}
 			itterations = 0;
 			trans = 0;
 			nothing_in_queue = 0;



More information about the Freeswitch-svn mailing list