Index: trunk/psModules/src/detrend/psPipe.c
===================================================================
--- trunk/psModules/src/detrend/psPipe.c	(revision 8848)
+++ trunk/psModules/src/detrend/psPipe.c	(revision 9432)
@@ -6,9 +6,10 @@
 #include <string.h>
 #include <sys/types.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <pslib.h>
-#include "pmFPA.h"
-#include "pmDetrendDB.h"
+#include <psPipe.h>
 
 void closePipes (int *stdin_fd, int *stdout_fd, int *stderr_fd)
@@ -104,5 +105,4 @@
 
         status = execvp (argv[0], argv);
-        // fprintf (stderr, "error starting remote shell process\n");
 
         // this statement exits the child, not the parent, process
@@ -133,4 +133,5 @@
     psPipe *pipe = psPipeAlloc();
 
+    pipe->pid    = pid;
     pipe->stdin  = stdin_fd[1];
     pipe->stdout = stdout_fd[0];
@@ -140,11 +141,70 @@
 }
 
-bool psPipeClose (psPipe *pipe)
-{
-
-    close (pipe->stdin);
-    close (pipe->stdout);
-    close (pipe->stderr);
-    return true;
-}
-
+// this function returns the exit status of the called function
+// or a value > 255 on an error
+int psPipeClose (psPipe *pipe)
+{
+    int close_status;
+    int exit_status;
+    int wait_status;
+    int result;
+
+    PS_ASSERT_PTR_NON_NULL(pipe, false);
+
+    close_status = true;
+    if (close (pipe->stdin) != 0) {
+        psError(PS_ERR_IO, true, "error closing the pipe stdin (pid %d, error %s)\n", pipe->pid, strerror(errno));
+        close_status = false;
+    }
+    if (close (pipe->stdout) != 0) {
+        psError(PS_ERR_IO, true, "error closing the pipe stdout (pid %d, error %s)\n", pipe->pid, strerror(errno));
+        close_status = false;
+    }
+    if (close (pipe->stderr) != 0) {
+        psError(PS_ERR_IO, true, "error closing the pipe sterr (pid %d, error %s)\n", pipe->pid, strerror(errno));
+        close_status = false;
+    }
+
+    // we expect the child process to have exited.
+    // wait for the exit condition, but no longer than 100ms
+    for (int i = 0; i < 10; i++) {
+        result = waitpid (pipe->pid, &wait_status, WNOHANG);
+        switch (result) {
+        case -1:   // error on waitpid
+            switch (errno) {
+            case ECHILD:
+                psError(PS_ERR_IO, true, "unknown PID, not a child process: %d\n", pipe->pid);
+                return 0x100;
+            default:
+                psAbort ("psPipeClose", "unexpected response to waitpid: %d\n", result);
+            }
+            break;
+
+        case 0:   // child not yet exited
+            usleep (10000);
+            continue;
+
+        default:
+            if (result != pipe->pid) {
+                psAbort ("psPipeClose", "waitpid error: mis-matched PID (%d vs %d).  programming error\n", result, pipe->pid);
+            }
+            if (WIFEXITED(wait_status)) {
+                exit_status = WEXITSTATUS(wait_status);
+                if (close_status) {
+                    return exit_status;
+                } else {
+                    return (0x100);
+                }
+            }
+            if (WIFSIGNALED(wait_status)) {
+                psError(PS_ERR_IO, true, "job %d exited on signal %d\n", pipe->pid, WTERMSIG(wait_status));
+                return (0x100 + WTERMSIG(wait_status));
+            }
+            if (WIFSTOPPED(wait_status)) {
+                psAbort ("psPipeClose", "waitpid returns 'stopped' programming error\n");
+            }
+        }
+    }
+    psError(PS_ERR_IO, true, "child process pid %d did not exit\n", pipe->pid);
+    return 0x100;
+}
