Index: trunk/psLib/src/imageops/psImageConvolve.c
===================================================================
--- trunk/psLib/src/imageops/psImageConvolve.c	(revision 28404)
+++ trunk/psLib/src/imageops/psImageConvolve.c	(revision 28405)
@@ -864,10 +864,8 @@
             PS_ARRAY_ADD_SCALAR(job->args, stop, PS_TYPE_S32);
             if (!psThreadJobAddPending(job)) {
-                psFree(job);
                 psFree(gaussNorm);
                 psFree(out);
                 return NULL;
             }
-            psFree(job);
         }
         if (!psThreadPoolWait(true)) {
@@ -1213,5 +1211,4 @@
                   if (!psThreadJobAddPending(job)) {
                       psError(PS_ERR_UNKNOWN, false, "Unable to smooth image");
-                      psFree(job);
                       psFree(calculation);
                       psFree(calcMask);
@@ -1219,5 +1216,4 @@
                       return false;
                   }
-                  psFree(job);
               }
               // wait here for the threaded jobs to finish (NOP if threading is not active)
@@ -1261,5 +1257,4 @@
                   if (!psThreadJobAddPending(job)) {
                       psError(PS_ERR_UNKNOWN, false, "Unable to smooth image");
-                      psFree(job);
                       psFree(calculation);
                       psFree(calcMask);
@@ -1267,5 +1262,4 @@
                       return false;
                   }
-                  psFree(job);
               }
 
@@ -1580,10 +1574,8 @@
             PS_ARRAY_ADD_SCALAR(job->args, 0x00, PS_TYPE_U8); // specify rows
             if (!psThreadJobAddPending(job)) {
-                psFree(job);
                 psFree(conv);
                 psFree(out);
                 return NULL;
             }
-            psFree(job);
         }
         if (!psThreadPoolWait(true)) {
@@ -1617,10 +1609,8 @@
             PS_ARRAY_ADD_SCALAR(job->args, 0xff, PS_TYPE_U8); // specify cols
             if (!psThreadJobAddPending(job)) {
-                psFree(job);
                 psFree(conv);
                 psFree(out);
                 return NULL;
             }
-            psFree(job);
         }
         if (!psThreadPoolWait(true)) {
Index: trunk/psLib/src/imageops/psImageCovariance.c
===================================================================
--- trunk/psLib/src/imageops/psImageCovariance.c	(revision 28404)
+++ trunk/psLib/src/imageops/psImageCovariance.c	(revision 28405)
@@ -169,5 +169,4 @@
                     return NULL;
                 }
-                psFree(job);
             } else {
                 out->kernel[y][x] = imageCovarianceCalculate(covar, kernel, x, y);
@@ -334,5 +333,4 @@
                     return NULL;
                 }
-                psFree(job);
             } else {
                 out->kernel[y][x] = imageCovarianceBin(covar, bin, binVal, x, y);
Index: trunk/psLib/src/sys/psThread.c
===================================================================
--- trunk/psLib/src/sys/psThread.c	(revision 28404)
+++ trunk/psLib/src/sys/psThread.c	(revision 28405)
@@ -99,5 +99,8 @@
 bool psThreadJobAddPending(psThreadJob *job)
 {
-    PS_ASSERT_THREAD_JOB_NON_NULL(job, false);
+    if (!job) {
+        // Asking for a no-op
+        return true;
+    }
 
     psThreadTask *task = psHashLookup(tasks, job->type); // Task to execute job
@@ -114,5 +117,5 @@
         }
         psListAdd(done, PS_LIST_TAIL, job);
-
+        psFree(job);
         return task->function(job);
     }
@@ -123,4 +126,5 @@
     }
     psListAdd(pending, PS_LIST_TAIL, job);
+    psFree(job);
     psThreadUnlock();
 
@@ -279,5 +283,5 @@
     for (int i = 0; i < nThreads; i++) {
         psThread *thread = pool->data[i] = psThreadAlloc(); // Thread for pool
-        if (!pthread_create(&threads[i], NULL, psThreadLauncher, thread)) {
+        if (pthread_create(&threads[i], NULL, psThreadLauncher, thread)) {
             psAbort("Unable to create thread");
         }
Index: trunk/psLib/src/sys/psThread.h
===================================================================
--- trunk/psLib/src/sys/psThread.h	(revision 28404)
+++ trunk/psLib/src/sys/psThread.h	(revision 28405)
@@ -73,10 +73,19 @@
 
 /// Add a pending job to the queue
+///
+/// This function swallows the provided job, so that the user no longer owns it.  This is because freeing the
+/// job is not thread-safe (its reference count is being changed within the threads) so we handle it ourselves
+/// and absolve the user from all responsibility.  If the user stores the job, he should only access it while
+/// threads are processing in code protected by psThreadLock/psThreadUnlock.
 bool psThreadJobAddPending(psThreadJob *job);
 
 /// Get a job off the queue of pending jobs
+///
+/// This function is not thread-safe.  Protect with psThreadLock/psThreadUnlock if threads are running.
 psThreadJob *psThreadJobGetPending(void);
 
 /// Get a job off the queue of done jobs
+///
+/// This function is not thread-safe.  Protect with psThreadLock/psThreadUnlock if threads are running.
 psThreadJob *psThreadJobGetDone(void);
 
@@ -115,5 +124,5 @@
 bool psThreadPoolFinalize(void);
 
-
+#if 0
 /// Add thread-specific data
 ///
@@ -134,5 +143,5 @@
 bool psThreadDataRemove(const char *name // Name of data
     );
-
+#endif
 
 /// @}
