Index: branches/eam_branches/ppStack.20211015/src/ppStackReadout.c
===================================================================
--- branches/eam_branches/ppStack.20211015/src/ppStackReadout.c	(revision 41842)
+++ branches/eam_branches/ppStack.20211015/src/ppStackReadout.c	(revision 41845)
@@ -19,4 +19,8 @@
                                          weightings, exposures, addVariance);
     thread->busy = false;
+
+    thread->status = job->results ? PPSTACK_THREAD_SUCCESS : PPSTACK_THREAD_FAILURE;
+
+    psAssert(job->results, "Stacking failed.");
 
     return job->results ? true : false;
@@ -48,4 +52,6 @@
     thread->busy = false;
 
+    thread->status = status ? PPSTACK_THREAD_SUCCESS : PPSTACK_THREAD_FAILURE;
+
     psAssert(status, "Stacking failed.");
 
@@ -68,8 +74,17 @@
     psVector *addVariance = options->matchChi2; // Additional variance when rejecting
 
-    job->results = ppStackReadoutInitial(config, outRO, thread->readouts, mask, weightings, exposures, addVariance);
+    // fprintf (stderr, "start thread %d : scan range %d - %d\n", thread->entry, thread->firstScan, thread->lastScan);
+
+    bool status = ppStackReadoutPercent(config, outRO, thread->readouts, mask, weightings, exposures, addVariance);
+
     thread->busy = false;
 
-    return job->results ? true : false;
+    thread->status = status ? PPSTACK_THREAD_SUCCESS : PPSTACK_THREAD_FAILURE;
+
+    // fprintf (stderr, "finished thread %d, status %d : scan range %d - %d\n", thread->entry, thread->status, thread->firstScan, thread->lastScan);
+
+    psAssert(status, "Stacking failed.");
+
+    return status;
 }
 
@@ -167,5 +182,5 @@
 
     int num = readouts->n;              // Number of inputs
-    psArray *stack = psArrayAlloc(num); // Array for stacking
+    psArray *stackData = psArrayAlloc(num); // Array of data to be stacked
 
     for (int i = 0; i < num; i++) {
@@ -182,12 +197,19 @@
         }
 
-        stack->data[i] = pmStackDataAlloc(ro, weightings->data.F32[i], exposures->data.F32[i],
+	// stackData is an array of pmStackData structures
+        stackData->data[i] = pmStackDataAlloc(ro, weightings->data.F32[i], exposures->data.F32[i],
                                           addVariance->data.F32[i]);
     }
 
-    if (!pmStackCombine(outRO, NULL, stack, maskBad, maskSuspect, maskBlank, kernelSize, iter,
+    if (!pmStackCombine(outRO, NULL, stackData, maskBad, maskSuspect, maskBlank, kernelSize, iter,
                         combineRej, combineSys, combineDiscard, useVariance, safe, nminpix, false)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to combine input readouts with rejection.");
-        psFree(stack);
+        psFree(stackData);
+	
+	// XXX EAM : if pmStackCombine fails above this return will cause the thread to block.
+	// The failure status results in a psThread.fault.  the psThreadLauncher function, which
+	// each background thread runs as a loop, will sleep until the fault is cleared externally
+	// by the handler.  psThreadPoolWait() catches, counts, and clears these faults, but
+	// ppStackThreadRead does not.  
         return false;
     }
@@ -197,5 +219,5 @@
     psArray *reject = psArrayAlloc(num);  // List of pixels rejected
     for (int i = 0; i < num; i++) {
-        pmStackData *data = stack->data[i]; // Data for this image
+        pmStackData *data = stackData->data[i]; // Data for this image
         if (!data) {
             continue;
@@ -208,5 +230,5 @@
         reject->data[i] = psMemIncrRefCounter(data->reject);
     }
-    psFree(stack);
+    psFree(stackData);
 
     //MEH change to trace
@@ -269,5 +291,5 @@
 
     int num = readouts->n;              // Number of inputs
-    psArray *stack = psArrayAlloc(num); // Array for stacking
+    psArray *stackData = psArrayAlloc(num); // Array of data to be stacked
 
     // We have rejection from a previous combination: combine without flagging pixels to inspect
@@ -294,5 +316,5 @@
                                              addVariance ? addVariance->data.F32[i] : NAN);
         data->reject = rejected ? psMemIncrRefCounter(rejected->data[i]) : NULL;
-        stack->data[i] = data;
+        stackData->data[i] = data;
 
         //MEH -- apply bscale offset before norm   
@@ -310,8 +332,8 @@
     }
 
-    if (!pmStackCombine(outRO, expRO, stack, maskBad, maskSuspect, maskBlank, 0, iter, combineRej,
+    if (!pmStackCombine(outRO, expRO, stackData, maskBad, maskSuspect, maskBlank, 0, iter, combineRej,
                         combineSys, combineDiscard, useVariance, safe, nminpix, rejected)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to combine input readouts.");
-        psFree(stack);
+        psFree(stackData);
         return false;
     }
@@ -329,5 +351,5 @@
     expChip->data_exists = true;
 
-    psFree(stack);
+    psFree(stackData);
 
     //MEH change to trace
@@ -338,6 +360,4 @@
     return true;
 }
-
-bool pmStackCombineByPercentile(pmReadout *outRO, psArray *stack, float minRange, float maxRange, psImageMaskType maskBad, psImageMaskType maskSuspect, psImageMaskType maskBlank);
 
 bool ppStackReadoutPercent(const pmConfig *config, pmReadout *outRO, const psArray *readouts,
@@ -353,4 +373,6 @@
     static int sectionNum = 0;          // Section number; for debugging outputs
 
+    // fprintf (stderr, "starting ReadoutPercent, %d\n", sectionNum);
+
     // Get the recipe values
     psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSTACK_RECIPE); // ppStack recipe
@@ -358,6 +380,6 @@
 
     bool mdok;                          // Status of MD lookup
-    float minRange = psMetadataLookupF32(&mdok, recipe, "COMBINE.MIN.RANGE"); // Combination threshold
-    float maxRange = psMetadataLookupF32(&mdok, recipe, "COMBINE.MAX.RANGE"); // Combination threshold
+    psF64 minRange = psMetadataLookupF32(&mdok, recipe, "COMBINE.MIN.RANGE"); // Combination threshold
+    psF64 maxRange = psMetadataLookupF32(&mdok, recipe, "COMBINE.MAX.RANGE"); // Combination threshold
 
     char defaultBlankStr[16] = "BLANK";
@@ -378,5 +400,5 @@
 
     int num = readouts->n;              // Number of inputs
-    psArray *stack = psArrayAlloc(num); // Array for stacking
+    psArray *stackData = psArrayAlloc(num); // Array of data to be stacked
 
     for (int i = 0; i < num; i++) {
@@ -393,14 +415,27 @@
         }
 
-        stack->data[i] = pmStackDataAlloc(ro, weightings->data.F32[i], exposures->data.F32[i],
-                                          addVariance->data.F32[i]);
-    }
-
-    if (!pmStackCombineByPercentile(outRO, stack, minRange, maxRange, maskBad, maskSuspect, maskBlank)) {
+        stackData->data[i] = pmStackDataAlloc(ro, weightings->data.F32[i], exposures->data.F32[i],
+					      addVariance->data.F32[i]);
+    }
+
+    if (!pmStackCombineByPercentile(outRO, stackData, minRange, maxRange, maskBad, maskSuspect, maskBlank)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to combine input readouts with rejection.");
-        psFree(stack);
+        psFree(stackData);
         return false;
     }
 
+    outRO->data_exists = true; // output readout
+    outRO->parent->data_exists = true; // output cell
+    outRO->parent->parent->data_exists = true; // output chip
+
+# if 0
+      pmCell *expCell = expRO->parent;    // Exposure cell
+      pmChip *expChip = expCell->parent;  // Exposure chip
+      expRO->data_exists = true;
+      expCell->data_exists = true;
+      expChip->data_exists = true;
+# endif
+
+    psFree(stackData);
     sectionNum++;
 
