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("socket call failed"
exit(1);
}
rc = bind(s, (struct sockaddr *)&local, sizeof(local));
if (rc < 0)
{
perror("bind call failure"
exit(1);
}
rc = listen(s, 5);
if (rc)
{
perror("listen call failed"
exit(1);
}
if((signal(SIGCHLD, reaper)) == SIG_ERR)
{
perror("signal disposition error"
exit(1);
}
for(;
{
s1 = accept(s, NULL, NULL);
if (s1 < 0)
{
if (errno!=EINTR)
{
perror("accept call failed"
exit(1);
}
}
else
key++;
switch(fork())
{
case -1:
perror("fork failed"
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, "%0.6llx", key);
rc = send(s1, buf, sizeof(buf), 0);
if (rc <= 0 && errno!=EBADF)
perror("send call failed"
}
void reaper(int i)
{
pid_t pid;
int statusp;
while((pid = waitpid(-1, &statusp, WNOHANG)) > 0)
;
return;
}
====================================================
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("socket call failed"
exit(1);
}
rc = bind(s, (struct sockaddr *)&local, sizeof(local));
if (rc < 0)
{
perror("bind call failure"
exit(1);
}
rc = listen(s, 5);
if (rc)
{
perror("listen call failed"
exit(1);
}
if((signal(SIGCHLD, reaper)) == SIG_ERR)
{
perror("signal disposition error"
exit(1);
}
for(;
{
s1 = accept(s, NULL, NULL);
if (s1 < 0)
{
if (errno!=EINTR)
{
perror("accept call failed"
exit(1);
}
}
else
key++;
switch(fork())
{
case -1:
perror("fork failed"
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, "%0.6llx", key);
rc = send(s1, buf, sizeof(buf), 0);
if (rc <= 0 && errno!=EBADF)
perror("send call failed"
}
void reaper(int i)
{
pid_t pid;
int statusp;
while((pid = waitpid(-1, &statusp, WNOHANG)) > 0)
;
return;
}
====================================================