about summary refs log tree commit diff
path: root/other
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2021-03-24 01:05:26 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2021-03-24 01:05:26 +0000
commit0be274c0efdd5c3d40be4366260722adfa72527f (patch)
tree7f3febd02837eed85f33e4eb86ba379dedf44e61 /other
parentb53a050bd31ac3ed6da1d546bc4f25cee0d69219 (diff)
downloadnetpbm-mirror-0be274c0efdd5c3d40be4366260722adfa72527f.tar.gz
netpbm-mirror-0be274c0efdd5c3d40be4366260722adfa72527f.tar.xz
netpbm-mirror-0be274c0efdd5c3d40be4366260722adfa72527f.zip
Handle program that doesn't consume all the input better
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@4064 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'other')
-rw-r--r--other/pamexec.c49
1 files changed, 46 insertions, 3 deletions
diff --git a/other/pamexec.c b/other/pamexec.c
index 3d1f5086..cbde81ac 100644
--- a/other/pamexec.c
+++ b/other/pamexec.c
@@ -18,6 +18,8 @@
 #include <stdbool.h>
 #include <string.h>
 #include <stdio.h>
+#include <signal.h>
+#include <setjmp.h>
 #include <errno.h>
 
 #include "pm_c_util.h"
@@ -26,6 +28,26 @@
 #include "mallocvar.h"
 #include "pam.h"
 
+
+/* About SIGPIPE:
+
+   Unix has a strange function where by default, if you write into a pipe when
+   the reading side of the pipe has been closed, it generates a signal (of
+   class SIGPIPE), but if you tell the OS to ignore signals of class SIGPIPE,
+   then instead of generating that signal, the system call to write to the
+   pipe just fails.
+
+   Pamexec writes to a pipe when it feeds an image to the user's program's
+   Standard Input.  Should the user's program close its end of the pipe (such
+   as by exiting) before reading the whole image, that would, if we did
+   nothing to deal with it, cause Pamexec to receive a SIGPIPE signal, which
+   would make the OS terminate Pamexec.
+
+   We don't want that, so we tell the OS to ignore SIGPIPE signals, so that
+   instead our attempt to write to the pipe just fails and we fail with a
+   meaningful error message.
+*/
+
 struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
@@ -108,9 +130,25 @@ pipeOneImage(FILE * const infileP,
 
     tuplerow = pnm_allocpamrow(&inpam);
 
-    for (row = 0; row < inpam.height; ++row) {
-        pnm_readpamrow(&inpam, tuplerow);
-        pnm_writepamrow(&outpam, tuplerow);
+    {
+        jmp_buf jmpbuf;
+        int rc;
+        rc = setjmp(jmpbuf);
+        if (rc == 0) {
+            pm_setjmpbuf(&jmpbuf);
+
+            for (row = 0; row < inpam.height; ++row) {
+                pnm_readpamrow(&inpam, tuplerow);
+                pnm_writepamrow(&outpam, tuplerow);
+            }
+        } else {
+            pm_setjmpbuf(NULL);
+            pm_error("Failed to read image and pipe it to program's "
+                     "Standard Input.  If previous messages indicate "
+                     "a broken pipe error, that means the program closed "
+                     "its Standard Error (possibly by exiting) before "
+                     "it had read the entire image>");
+        }
     }
 
     pnm_freepamrow(tuplerow);
@@ -171,6 +209,11 @@ main(int argc, const char *argv[]) {
 
     parseCommandLine(argc, argv, &cmdline);
 
+    /* Make write to closed pipe fail rather than generate a signal.
+       See comments at top of program.
+    */
+    signal(SIGPIPE, SIG_IGN);
+
     ifP = pm_openr(cmdline.inputFileName);
 
     for (eof = false, imageSeq = 0; !eof; ++imageSeq) {