Re: [Exim] SIGCHLD - SIG_IGN errors under Linux

Top Page
Delete this message
Reply to this message
Author: Philip Hazel
Date:  
To: Vallimar
CC: exim-users
Subject: Re: [Exim] SIGCHLD - SIG_IGN errors under Linux
On Wed, 19 Feb 2003, Vallimar wrote:

>
> I'm using the latest glibc RPM's from RedHat Rawhide and they, or
> the Glibc maintainers, have started a campaign it seems to get people
> to fix a coding 'mistake' of setting SIGCHLD to SIG_IGN.


The handling of SIGCHLD has been one of the causes of multiple problems
in Exim, because of the different ways that different OS handle it. Just
grep the ChangeLog files for Exim 3 and Exim 4...

In fact, there is already another fix lined up for the next release:

 1. Found another case where SIGCHLD is being ignored (a child process for
    handling a filter file) and so the wait() doesn't find the subprocess. This
    came to light as a result of extra logging introduced as part of the
    4.12/14 fix. Now Exim is careful to set SIGCHLD handling to its default
    (i.e. to be noticed) for this particular subprocess. (It already has this
    code for other cases where it uses subprocesses.)


I wonder if this is the case that is hitting you?

> * application bug: exim(<pid>) has SIGCHLD set to SIG_IGN but calls wait().
> * (see the NOTES section of 'man 2 wait'). Workaround activated.


That certainly looks like the same situation. Can you tell if a filter
file was involved when you saw this on your log?

> I'm not subscribed to the list, so if you do create a patch, please
> make sure to cc me so I might try it out.


Patch below (created some time back).

--
Philip Hazel            University of Cambridge Computing Service,
ph10@???      Cambridge, England. Phone: +44 1223 334714.




*** exim-4.12/src/rda.c     Wed Dec 18 10:28:03 2002
--- rda.c    Wed Dec 18 11:35:25 2002
***************
*** 489,494 ****
--- 489,495 ----
  int yield, status;
  pid_t pid;
  uschar *data;
+ void (*oldsignal)(int);


  DEBUG(D_route) debug_printf("rda_interpret (%s): %s\n",
    (rdata->isfile)? "file" : "string", rdata->string);
***************
*** 542,547 ****
--- 543,553 ----
    log_write(0, LOG_MAIN|LOG_PANIC_DIE, "creation of pipe for filter or "
      ":include: failed for %s: %s", rname, strerror(errno));


+ /* Ensure that SIGCHLD is set to SIG_DFL before forking, so that the child
+ process can be waited for. We sometimes get here with it set otherwise. Save
+ the old state for resetting on the wait. */
+
+ oldsignal = signal(SIGCHLD, SIG_DFL);
  if ((pid = fork()) == 0)
    {
    header_line *waslast = header_last;   /* Save last header */
***************
*** 831,836 ****
--- 837,843 ----
    }


close(fd);
+ signal(SIGCHLD, oldsignal); /* restore */
return yield;

/* Come here is there's a shambles in transferring the data over the pipe. */