about summary refs log tree commit diff
path: root/converter/other/pnmtops.c
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2013-11-16 03:24:24 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2013-11-16 03:24:24 +0000
commitca5af957777d572bdd9a462ef2e3d38905fd4a3d (patch)
tree4af8b5bbfa436dcb418832a5ac2fb99619d1bcbe /converter/other/pnmtops.c
parentfcba27aec24b5bfb48a7e9aa5e395b46e973a00f (diff)
downloadnetpbm-mirror-ca5af957777d572bdd9a462ef2e3d38905fd4a3d.tar.gz
netpbm-mirror-ca5af957777d572bdd9a462ef2e3d38905fd4a3d.tar.xz
netpbm-mirror-ca5af957777d572bdd9a462ef2e3d38905fd4a3d.zip
Make sure SIGCHLD isn't set to ignore
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@2035 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter/other/pnmtops.c')
-rw-r--r--converter/other/pnmtops.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/converter/other/pnmtops.c b/converter/other/pnmtops.c
index 29326508..115f9d29 100644
--- a/converter/other/pnmtops.c
+++ b/converter/other/pnmtops.c
@@ -42,6 +42,8 @@
 #include <unistd.h>
 #include <assert.h>
 #include <string.h>
+#include <errno.h>
+#include <signal.h>
 #ifndef NOFLATE
 #include <zlib.h>
 #endif
@@ -52,6 +54,37 @@
 #include "shhopt.h"
 #include "nstring.h"
 
+
+
+static void
+setSignals() {
+/*----------------------------------------------------------------------------
+   Set up the process-global signal-related state.
+
+   Note that we can't rely on defaults, because much of this is inherited
+   from the process that forked and exec'ed this program.
+-----------------------------------------------------------------------------*/
+    /* See waitForChildren() for why we do this to SIGCHLD */
+
+    struct sigaction sigchldAction;
+    int rc;
+    sigset_t emptySet;
+
+    sigemptyset(&emptySet);
+
+    sigchldAction.sa_handler = SIG_DFL;
+    sigchldAction.sa_mask = emptySet;
+    sigchldAction.sa_flags = SA_NOCLDSTOP;
+
+    rc = sigaction(SIGCHLD, &sigchldAction, NULL);
+
+    if (rc != 0)
+        pm_error("sigaction() to set up signal environment failed, "
+                 "errno = %d (%s)", errno, strerror(errno));
+}
+
+
+
 struct cmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
@@ -966,6 +999,15 @@ waitForChildren(const pid_t * const pidList) {
    Wait for all child processes with PIDs in pidList[] to exit.
    In pidList[], end-of-list is marked with a special zero value.
 -----------------------------------------------------------------------------*/
+    /* There's an odd behavior in Unix such that if you have set the
+       action for SIGCHLD to ignore the signal (even though ignoring the
+       siganl is the default), the process' children do not become
+       zombies.  Consequently, waitpid() always fails with ECHILD - but
+       nonetheless waits for the child to exit.
+    
+       We expect the process not to have the action for SIGCHLD set that
+       way.
+    */
     unsigned int i;
 
     for (i = 0; pidList[i]; ++i) {
@@ -977,7 +1019,8 @@ waitForChildren(const pid_t * const pidList) {
 
         rc = waitpid(pidList[i], &status, 0);
         if (rc == -1)
-            pm_error ("waitpid() for child %u failed", i);
+            pm_error ("waitpid() for child %u failed, errno=%d (%s)",
+                      i, errno, strerror(errno));
         else if (status != EXIT_SUCCESS)
             pm_error ("Child process %u terminated abnormally", i);
     }
@@ -2021,6 +2064,8 @@ main(int argc, const char * argv[]) {
 
     pm_proginit(&argc, argv);
 
+    setSignals();
+
     parseCommandLine(argc, argv, &cmdline);
 
     verbose = cmdline.verbose;