diff --git a/indra/llcommon/tests/llprocesslauncher_test.cpp b/indra/llcommon/tests/llprocesslauncher_test.cpp
index 4d14e1be532651f07cdb5f7687a863185ba5bd22..ca06b3164e74ce3db3f9821924b2a0b3616c2b3d 100644
--- a/indra/llcommon/tests/llprocesslauncher_test.cpp
+++ b/indra/llcommon/tests/llprocesslauncher_test.cpp
@@ -17,6 +17,7 @@
 // STL headers
 #include <vector>
 // std headers
+#include <errno.h>
 // external library headers
 #include "llapr.h"
 #include "apr_thread_proc.h"
@@ -71,11 +72,53 @@ namespace tut
     typedef llprocesslauncher_group::object object;
     llprocesslauncher_group llprocesslaunchergrp("llprocesslauncher");
 
+    struct Item
+    {
+        Item(): tries(0) {}
+        unsigned    tries;
+        std::string which;
+        std::string what;
+    };
+
     template<> template<>
     void object::test<1>()
     {
         set_test_name("raw APR nonblocking I/O");
 
+        // Create a script file in a temporary place.
+        const char* tempdir = NULL;
+        aprchk(apr_temp_dir_get(&tempdir, apr.pool));
+
+        // Construct a temp filename template in that directory.
+        char *tempname = NULL;
+        aprchk(apr_filepath_merge(&tempname, tempdir, "testXXXXXX", 0, apr.pool));
+
+        // Create a temp file from that template.
+        apr_file_t* fp = NULL;
+        aprchk(apr_file_mktemp(&fp, tempname, APR_CREATE | APR_WRITE | APR_EXCL, apr.pool));
+
+        // Write it.
+        const char script[] =
+            "import sys\n"
+            "import time\n"
+            "\n"
+            "time.sleep(2)\n"
+            "print >>sys.stdout, \"stdout after wait\"\n"
+            "sys.stdout.flush()\n"
+            "time.sleep(2)\n"
+            "print >>sys.stderr, \"stderr after wait\"\n"
+            "sys.stderr.flush()\n"
+            ;
+        apr_size_t len(sizeof(script)-1);
+        aprchk(apr_file_write(fp, script, &len));
+        aprchk(apr_file_close(fp));
+
+        // Arrange to track the history of our interaction with child: what we
+        // fetched, which pipe it came from, how many tries it took before we
+        // got it.
+        std::vector<Item> history;
+        history.push_back(Item());
+
         apr_procattr_t *procattr = NULL;
         aprchk(apr_procattr_create(&procattr, apr.pool));
         aprchk(apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK, APR_CHILD_BLOCK));
@@ -84,8 +127,7 @@ namespace tut
         std::vector<const char*> argv;
         apr_proc_t child;
         argv.push_back("python");
-        argv.push_back("-c");
-        argv.push_back("raise RuntimeError('Hello from Python!')");
+        argv.push_back(tempname);
         argv.push_back(NULL);
 
         aprchk(apr_proc_create(&child, argv[0],
@@ -110,24 +152,35 @@ namespace tut
                 apr_status_t rv = apr_file_gets(buf, sizeof(buf), iterfiles[i].second);
                 if (APR_STATUS_IS_EOF(rv))
                 {
-                    std::cout << "(EOF on " << iterfiles[i].first << ")\n";
+//                  std::cout << "(EOF on " << iterfiles[i].first << ")\n";
+                    history.back().which = iterfiles[i].first;
+                    history.back().what  = "*eof*";
+                    history.push_back(Item());
                     outfiles.erase(outfiles.begin() + i);
                     continue;
                 }
-                if (rv != APR_SUCCESS)
+                if (rv == EWOULDBLOCK)
                 {
-                    std::cout << "(waiting; apr_file_gets(" << iterfiles[i].first << ") => " << rv << ": " << apr.strerror(rv) << ")\n";
+//                  std::cout << "(waiting; apr_file_gets(" << iterfiles[i].first << ") => " << rv << ": " << apr.strerror(rv) << ")\n";
+                    ++history.back().tries;
                     continue;
                 }
+                ensure_equals(rv, APR_SUCCESS);
                 // Is it even possible to get APR_SUCCESS but read 0 bytes?
                 // Hope not, but defend against that anyway.
                 if (buf[0])
                 {
-                    std::cout << iterfiles[i].first << ": " << buf;
-                    // Just for pretty output... if we only read a partial
-                    // line, terminate it.
-                    if (buf[strlen(buf) - 1] != '\n')
-                        std::cout << "...\n";
+//                  std::cout << iterfiles[i].first << ": " << buf;
+                    history.back().which = iterfiles[i].first;
+                    history.back().what.append(buf);
+                    if (buf[strlen(buf) - 1] == '\n')
+                        history.push_back(Item());
+                    else
+                    {
+                        // Just for pretty output... if we only read a partial
+                        // line, terminate it.
+//                      std::cout << "...\n";
+                    }
                 }
             }
             sleep(1);
@@ -141,9 +194,29 @@ namespace tut
         apr_status_t rv;
         while (! APR_STATUS_IS_CHILD_DONE(rv = apr_proc_wait(&child, &rc, &why, APR_NOWAIT)))
         {
-            std::cout << "child not done (" << rv << "): " << apr.strerror(rv) << '\n';
+//          std::cout << "child not done (" << rv << "): " << apr.strerror(rv) << '\n';
             sleep(0.5);
         }
-        std::cout << "child done: rv = " << rv << " (" << apr.strerror(rv) << "), why = " << why << ", rc = " << rc << '\n';
+//      std::cout << "child done: rv = " << rv << " (" << apr.strerror(rv) << "), why = " << why << ", rc = " << rc << '\n';
+        ensure_equals(rv, APR_CHILD_DONE);
+        ensure_equals(why, APR_PROC_EXIT);
+        ensure_equals(rc, 0);
+
+        // Remove temp script file
+        aprchk(apr_file_remove(tempname, apr.pool));
+
+        // Beyond merely executing all the above successfully, verify that we
+        // obtained expected output -- and that we duly got control while
+        // waiting, proving the non-blocking nature of these pipes.
+        ensure("blocking I/O on child pipe (0)", history[0].tries);
+        ensure_equals(history[0].which, "out");
+        ensure_equals(history[0].what,  "stdout after wait\n");
+        ensure("blocking I/O on child pipe (1)", history[1].tries);
+        ensure_equals(history[1].which, "out");
+        ensure_equals(history[1].what,  "*eof*");
+        ensure_equals(history[2].which, "err");
+        ensure_equals(history[2].what,  "stderr after wait\n");
+        ensure_equals(history[3].which, "err");
+        ensure_equals(history[3].what,  "*eof*");
     }
 } // namespace tut