6f949e90b1ba3de976455fbcf9da21897761d134
markd
  Fri Oct 29 16:11:58 2021 -0700
add timeout option to pipeline to allow kill long-running pipelines, especially ones run from CGIs

diff --git src/inc/pipeline.h src/inc/pipeline.h
index 27f6f37..441148e 100644
--- src/inc/pipeline.h
+++ src/inc/pipeline.h
@@ -69,68 +69,76 @@
 enum pipelineOpts
 /* pipeline options bitset */
     {
     pipelineRead       = 0x01, /* read from pipeline */
     pipelineWrite      = 0x02, /* write to pipeline */
     pipelineNoAbort    = 0x04, /* don't abort if a process exits non-zero,
                                 * wait will return exit code instead.
                                 * Still aborts if process signals. */
     pipelineMemInput   = 0x08, /* pipeline takes input from memory (internal) */
     pipelineAppend     = 0x10, /* Append to output file (used only with pipelineWrite) */
     pipelineSigpipe    = 0x20  /* enable sigpipe in the children and don't treat
                                   as an error in the parent */
     };
 
 struct pipeline *pipelineOpenFd(char ***cmds, unsigned opts,
-                                int otherEndFd, int stderrFd);
+                                int otherEndFd, int stderrFd,
+                                unsigned int timeout);
 /* Create a pipeline from an array of commands.  Each command is an array of
  * arguments.  Shell expansion is not done on the arguments.  If pipelineRead
  * is specified, the output of the pipeline is readable from the pipeline
  * object.  If pipelineWrite is specified, the input of the pipeline is
- * writable from the pipeline object. */
+ * writable from the pipeline object.  If timeout is > 0, pipeline is killed
+ * after timeout seconds. */
 
 struct pipeline *pipelineOpen(char ***cmds, unsigned opts,
-                              char *otherEndFile, char *stderrFile);
+                              char *otherEndFile, char *stderrFile,
+                              unsigned int timeout);
 /* Create a pipeline from an array of commands.  Each command is an array of
  * arguments.  Shell expansion is not done on the arguments.  If pipelineRead
  * is specified, the output of the pipeline is readable from the pipeline
  * object.  If pipelineWrite is specified, the input of the pipeline is
  * writable from the pipeline object.  If stderrFile is NULL, stderr is inherited,
- * otherwise it is redirected to this file.
+ * otherwise it is redirected to this file.   If timeout is > 0, pipeline is killed
+ * after timeout seconds.
  */
 
 void pipelineDumpCmds(char ***cmds);
 /* Dump out pipeline-formatted commands to stdout for debugging. */
 
 struct pipeline *pipelineOpenMem(char ***cmds, unsigned opts,
                                  void *otherEndBuf, size_t otherEndBufSize,
-                                 int stderrFd);
+                                 int stderrFd, unsigned int timeout);
 /* Create a pipeline from an array of commands, with the pipeline input/output
  * in a memory buffer.  See pipeline.h for full documentation.  Currently only
- * input to a read pipeline is supported  */
+ * input to a read pipeline is supported   If timeout is > 0, pipeline is killed
+ * after timeout seconds. */
 
 struct pipeline *pipelineOpenFd1(char **cmd, unsigned opts,
-                                 int otherEndFd, int stderrFd);
+                                 int otherEndFd, int stderrFd,
+                                 unsigned int timeout);
 /* like pipelineOpenFd(), only takes a single command */
 
 struct pipeline *pipelineOpen1(char **cmd, unsigned opts,
-                               char *otherEndFile, char *stderrFile);
+                               char *otherEndFile, char *stderrFile,
+                               unsigned int timeout);
 /* like pipelineOpen(), only takes a single command */
 
 struct pipeline *pipelineOpenMem1(char **cmd, unsigned opts,
                                   void *otherEndBuf, size_t otherEndBufSize,
-                                  int stderrFd);
+                                  int stderrFd,
+                                  unsigned int timeout);
 /* like pipelineOpenMem(), only takes a single command */
 
 char *pipelineDesc(struct pipeline *pl);
 /* Get the desciption of a pipeline for use in error messages */
 
 int pipelineFd(struct pipeline *pl);
 /* Get the file descriptor for a pipeline */
 
 FILE *pipelineFile(struct pipeline *pl);
 /* Get a FILE object wrapped around the pipeline.  Do not close the FILE, is
  * owned by the pipeline object.  A FILE is created on first call to this
  * function.  Subsequent calls return the same FILE.*/
 
 struct lineFile *pipelineLineFile(struct pipeline *pl);
 /* Get a lineFile object wrapped around the pipeline.  Do not close the