Index: /tags/ipp-20100610/psLib/src/db/psDB.c
===================================================================
--- /tags/ipp-20100610/psLib/src/db/psDB.c	(revision 28351)
+++ /tags/ipp-20100610/psLib/src/db/psDB.c	(revision 28352)
@@ -1524,9 +1524,24 @@
             }
         case PS_DATA_F64: {
-                bind[i].length  = 0;
-                bind[i].buffer  = &item->data.F64;
-                bind[i].is_null = psDBIsPTypeNaN(item->type, &item->data.F64) ? &isNull : NULL;
-                break;
-            }
+            // This hack is to work around a MySQL bug, where values of DBL_MAX are dumped (as text) with
+            // insufficient digits, causing the value to be rounded outside the bounds of DBL_MAX
+            // (specifically, -1.7976931348623157e+308 gets dumped as -1.79769313486232e+308 which is less
+            // than -DBL_MAX), which cannot then be loaded by MySQL.  We assume that we're using doubles for
+            // additional precision compared to floats, and not for additional size, so limiting to the
+            // maximum value of a float is not damaging.
+            if (item->data.F64 < -FLT_MAX) {
+                psWarning("Saturating double value at -FLT_MAX to work around MySQL bug: %lf --> %lf",
+                          item->data.F64, -FLT_MAX);
+                item->data.F64 = -FLT_MAX;
+            } else if (item->data.F64 > FLT_MAX) {
+                psWarning("Saturating double value at FLT_MAX to work around MySQL bug: %lf --> %lf",
+                          item->data.F64, FLT_MAX);
+                item->data.F64 = FLT_MAX;
+            }
+            bind[i].length  = 0;
+            bind[i].buffer  = &item->data.F64;
+            bind[i].is_null = psDBIsPTypeNaN(item->type, &item->data.F64) ? &isNull : NULL;
+            break;
+        }
         case PS_DATA_BOOL: {
                 // XXX: ASC HACK NOTE (2005/06/03): set extreme bytes to the
Index: /tags/ipp-20100610/psLib/src/sys/psThread.c
===================================================================
--- /tags/ipp-20100610/psLib/src/sys/psThread.c	(revision 28351)
+++ /tags/ipp-20100610/psLib/src/sys/psThread.c	(revision 28352)
@@ -7,4 +7,13 @@
 #include <unistd.h>
 #include <string.h>
+
+// Backtrace to help nail down bugs
+#ifdef HAVE_BACKTRACE
+#include <execinfo.h>
+#include <stdlib.h>
+#define BACKTRACE_BUFFER_SIZE 256       // Maximum size of backtrace
+static void **bt_buffer = NULL;         // Backtrace buffer
+static int bt_size = 0;                 // Backtrace buffer size
+#endif
 
 #include "psAssert.h"
@@ -33,4 +42,5 @@
 static psArray *tsd = NULL;             // Thread-specific data
 
+
 /***** basic thread functions *****/
 
@@ -91,4 +101,8 @@
     PS_ASSERT_THREAD_JOB_NON_NULL(job, false);
 
+    psThreadTask *task = psHashLookup(tasks, job->type); // Task to execute job
+    psAssert(task, "Unable to find task %s", job->type);
+    psAssert(job->args->n == task->nArgs, "invalid number of arguments to %s", task->type);
+
     // if we failed to call psThreadPoolInit, or we called it with nThreads == 0,
     // find the matching function and just run it.
@@ -101,8 +115,4 @@
         psListAdd(done, PS_LIST_TAIL, job);
 
-        // find the corresponding task and run it
-        psThreadTask *task = psHashLookup(tasks, job->type); // Task to execute job
-        psAssert(task, "Unable to find task %s", job->type);
-        psAssert(job->args->n == task->nArgs, "invalid number of arguments to %s", task->type);
         return task->function(job);
     }
@@ -209,4 +219,23 @@
 
         psThreadTask *task = psHashLookup(tasks, job->type); // Task to execute job
+#ifdef HAVE_BACKTRACE
+        if (!task && bt_buffer) {
+            psLogMsg("psLib.sys", PS_LOG_ABORT, "Backtrace of waiter:\n");
+            char **strings = backtrace_symbols((void *const *)bt_buffer, bt_size);
+            psLogMsg("psLib.sys", PS_LOG_ABORT, "Backtrace depth: %d", bt_size);
+            for (int i = 0; i < bt_size; i++) {
+                char *caller = strchr(strings[i], '(');
+                if (caller) {
+                    caller++;
+                    size_t callerLength = abs(strchr(caller, '+') - caller);
+                    psString name = psStringNCopy(caller, callerLength);
+                    psLogMsg("psLib.sys", PS_LOG_ABORT, "Backtrace %d: %s", i, name);
+                    psFree(name);
+                } else {
+                    psLogMsg("psLib.sys", PS_LOG_ABORT, "Backtrace %d: (unknown)", i);
+                }
+            }
+        }
+#endif
         psAssert(task, "Couldn't find thread task %s", job->type);
         psAssert(job->args->n == task->nArgs,
@@ -282,4 +311,12 @@
         return true;
     }
+
+#ifdef HAVE_BACKTRACE
+    if (bt_buffer) {
+        psFree(bt_buffer);
+    }
+    bt_buffer = psAlloc(BACKTRACE_BUFFER_SIZE * sizeof(void *));
+    bt_size = backtrace(bt_buffer, BACKTRACE_BUFFER_SIZE);
+#endif
 
     while (1) {
@@ -343,4 +380,10 @@
     tsd = NULL;
 
+#ifdef HAVE_BACKTRACE
+    if (bt_buffer) {
+        psFree(bt_buffer);
+    }
+#endif
+
     return true;
 }
