On Mon, Nov 20, 2006 at 11:20:41AM -0500, Tom Lane wrote:
> Stephen Harris <lists@spuddy.org> writes:
> > On Fri, Nov 17, 2006 at 11:40:36PM -0500, Tom Lane wrote:
> >> [ thinks for a bit... ] Another issue is that there'd be a race
> >> condition during backend start: if the postmaster tries to kill -PID
> >> before the backend has managed to execute setsid, it wouldn't work.
>
> > *ponder* Bugger. Standard solutions (eg try three times with a second
> > pause) would mitigate this, but.... Hmm.
>
> I think we could make it work if the postmaster does this:
>
> kill(child_pid, SIGxxx);
> #ifdef HAVE_SETSID
> kill(-child_pid, SIGxxx);
> #endif
That should work. I just created a dummy test case where a process forks
a child, the child does setsid and then forks 3 times, so 8 processes
all in the new process group. The original parent sleeps for 3 seconds then
kills the original child (the process group leader) then sleeps 3 more seconds
and then kills the process group. A simple sig handler shows the signal
being received by the remaining children.
Tested on RHEL4 (2.6.9-42.0.3.ELsmp) and Solaris 10 (Sparc) and got the
same results.
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void sig(int x)
{ int y=getpid(); printf("Process %d got signal\n",y); exit(0);
}
void do_child()
{ setsid(); fork(); fork(); fork();
printf("%d sleeping for a long time!\n",(int)getpid()); sleep(10000);
}
int main()
{ signal(SIGQUIT,&sig); signal(SIGCLD,SIG_IGN); int ch=fork();
if (ch==0) { do_child(); } else { int e; sleep(3); printf("Killing first child\n"); printf("Return is:
%d\n",e=kill(ch,SIGQUIT)); if (e) { perror("Bad kill"); } sleep(3); printf("Killing process group\n");
printf("Returnis: %d\n",e=kill(-ch,SIGQUIT)); if (e) { perror("Bad kill"); } }
exit(0);
}
--
rgds
Stephen