64435c8709f85a481ae55ab6ef76639fc7becba8
markd
  Thu Apr 6 12:09:05 2023 -0700
don't close stdin/stdout of pipeline if they were not opened by by the pipeline

diff --git src/lib/tests/pipelineTester.c src/lib/tests/pipelineTester.c
index b826e29..7ea64d1 100644
--- src/lib/tests/pipelineTester.c
+++ src/lib/tests/pipelineTester.c
@@ -24,61 +24,64 @@
     "double quote maybe used to quote words.\n"
     "\n"
     "Options:\n"
     "  -exitCode=n - run with no-abort and expect this error code,\n"
     "   which can be zero.\n"
     "  -write - create a write pipeline\n"
     "  -memApi - test memory buffer API\n"
     "  -pipeData=file - for a read pipeline, data read from the pipeline is copied\n"
     "   to this file for verification.  For a write pipeline, data from this\n"
     "   file is written to the pipeline.\n"
     "  -otherEnd=file - file for other end of pipeline\n"
     "  -stderr=file - file for stderr of pipeline\n"
     "  -fdApi - use the file descriptor API\n"
     "  -sigpipe - enable SIGPIPE.\n"
     "  -maxNumLines=n - read or write this many lines and close (for testing -sigpipe)\n"
+    "  -executeTwice - turn test twice, regression for bug were multiple runs failed\n"
     "  -timeout=n - timeout, in seconds\n",
     msg);
 }
 
 static struct optionSpec options[] =
 {
     {"exitCode", OPTION_INT},
     {"write", OPTION_BOOLEAN},
     {"memApi", OPTION_BOOLEAN},
     {"pipeData", OPTION_STRING},
     {"otherEnd", OPTION_STRING},
     {"stderr", OPTION_STRING},
     {"fdApi", OPTION_BOOLEAN},
     {"sigpipe", OPTION_BOOLEAN},
     {"maxNumLines", OPTION_INT},
     {"timeout", OPTION_INT},
+    {"executeTwice", OPTION_BOOLEAN},
     {NULL, 0},
 };
 
 /* options from command line */
 boolean noAbort = FALSE;  /* don't abort, check exit code */
 int expectExitCode = 0;   /* expected exit code */
 boolean fdApi = FALSE; /* use the file descriptor API */
 boolean isWrite = FALSE; /* make a write pipeline */
 boolean memApi = FALSE; /* test memory buffer API */
 boolean sigpipe = FALSE; /* enable sigpipe */
 int maxNumLines = INT_MAX;  /* number of lines to read or write */
 char *pipeDataFile = NULL;   /* use for input or output to the pipeline */
 char *otherEndFile = NULL;   /* file for other end of pipeline */
 char *stderrFile = NULL;   /* file for other stderr of pipeline */
 unsigned int timeout = 0;  /* timeout to apply */
+boolean executeTwice = FALSE;  /* execute test twice */
 
 int countOpenFiles()
 /* count the number of opens.  This is used to make sure no stray
  * pipes have been left open. */
 {
 int cnt = 0;
 int fd;
 struct stat statBuf;
 for (fd = 0; fd < 64; fd++)
     {
     if (fstat(fd, &statBuf) == 0)
         cnt++;
     }
 return cnt;
 }
@@ -270,27 +273,30 @@
 {
 optionInit(&argc, argv, options);
 if (argc < 2)
     usage("wrong number of args");
 if (optionExists("exitCode"))
     {
     noAbort = TRUE;
     expectExitCode = optionInt("exitCode", 0);
     }
 isWrite = optionExists("write");
 memApi = optionExists("memApi");
 fdApi = optionExists("fdApi");
 sigpipe = optionExists("sigpipe");
 maxNumLines = optionInt("maxNumLines", INT_MAX);
 timeout = optionInt("timeout", 0);
+executeTwice = optionExists("executeTwice");
 if (fdApi && memApi)
     errAbort("can't specify both -fdApi and -memApi");
 pipeDataFile = optionVal("pipeData", NULL);
 otherEndFile = optionVal("otherEnd", NULL);
 if (fdApi && (otherEndFile == NULL))
     errAbort("-fdApi requires -otherEndFile");
 if (memApi && (otherEndFile == NULL))
     errAbort("-memApi requires -otherEndFile");
 stderrFile = optionVal("stderr", NULL);
 pipelineTester(argc-1, argv+1);
+if (executeTwice)
+    pipelineTester(argc-1, argv+1);
 return 0;
 }