Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

UNIX zombies SIGCHLD handler not working!?

Status
Not open for further replies.

milenko

Programmer
Nov 13, 2002
8
US
Hello, I have a simple socket program design to run on the same machine the clients will appear on. It's very simple, it just returns a unique number to shell (like a primary key). The reason is so concurrent shell scripts can use the number returned to name files without clobbering each others output -- every call to the client in a shell script returns a unique number no other process will get.

So the program (which compiles under Solaris and AIX) does all the usual stuff, makes a socket, binds it, listens, registers a signal handler for SIGCHLD which calls waitpid, and then forks and deals with the results if it's a child.

BUT THE CHILD PROCESSES ARE *STILL* ZOMBIES EVEN THOUGH WAITPID() IS BEING CALLED! I even tried wait3(), and wait(). I soon hit the system process limit because the children are not being checked after exiting.

Here is the very simple code. Any ideas?
===============================================
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <errno.h>

void relay_messages(void);
void reaper(int);
int s, s1, rc;
char buf[128];
unsigned long long key;
extern int errno;

int main (void)
{
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(7500+getuid());
local.sin_addr.s_addr = htonl( INADDR_ANY );

s = socket( AF_INET, SOCK_STREAM, 0);
if (s < 0)
{
perror(&quot;socket call failed&quot;);
exit(1);
}

rc = bind(s, (struct sockaddr *)&local, sizeof(local));
if (rc < 0)
{
perror(&quot;bind call failure&quot;);
exit(1);
}

rc = listen(s, 5);
if (rc)
{
perror(&quot;listen call failed&quot;);
exit(1);
}

if((signal(SIGCHLD, reaper)) == SIG_ERR)
{
perror(&quot;signal disposition error&quot;);
exit(1);
}

for(;;)
{

s1 = accept(s, NULL, NULL);
if (s1 < 0)
{
if (errno!=EINTR)
{
perror(&quot;accept call failed&quot;);
exit(1);
}
}
else
key++;

switch(fork())
{
case -1:
perror(&quot;fork failed&quot;);
close(s);
close(s1);
exit(1);
case 0:
relay_messages();
_exit(0);
default:
close(s1);
continue;
}

}
exit(0);

}

void relay_messages(void)
{
memset(buf, 0, sizeof(buf));
sprintf(buf, &quot;%0.6llx&quot;, key);
rc = send(s1, buf, sizeof(buf), 0);
if (rc <= 0 && errno!=EBADF)
perror(&quot;send call failed&quot;);
}

void reaper(int i)
{
pid_t pid;
int statusp;

while((pid = waitpid(-1, &statusp, WNOHANG)) > 0)
;

return;
}
====================================================
 
For what it's worth,

(1) signal(SIGCHLD, SIG_IGN) fixes the problem

(2) My own registered handler only catches the first time! Not interested in re-registering the handler within the handler.

It still doesn't explain why my signal handler gets &quot;unregistered&quot; after one use. That basically stinks... and most books (including Stevens) never mention this in their socket programming examples.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top