krikara
krikara

Reputation: 2435

Sockets program with signal catcher

I am trying to make my server.c program be able to handle zombie processes. Originally, I found the line signal(SIGCHLD,SIG_IGN); from linuxhowtos.org/C_C++/socket. This works like a charm. I can connect with a client then close the client and everything still runs smoothly.

However, I am trying to replace SIG_IGN with SigCatcher as written in the article and my server program starts going haywire when the client is closed(it infinitely keeps receiving "2" and outputs that).

I have tried both wait3(NULL,WNOHANG,NULL) as well as wait(-1) but neither of these solved the problem. What exactly should I be trying to do here?

void *SignalCatcher(int n)
{
  wait3(NULL,WNOHANG,NULL);
}

This is what my main looks like:

   //signal(SIGCHLD, SIG_IGN);
   signal(SIGCHLD, SignalCatcher);

   for(;;)
   {
      clilen=sizeof(cliaddr);
      connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);


      if ((childpid = fork()) == 0)
      {
         close (listenfd);

         for(;;)
         {
            n = recvfrom(connfd,mesg,1000,0,(struct sockaddr*)&cliaddr,&clilen);
            write(connfd , "" , 1);
            mesg[n] = 0;
            printf("Received the following:\n");
            printf("%s",mesg);

         }

      }
      close(connfd);
   }

Upvotes: 1

Views: 611

Answers (2)

wildplasser
wildplasser

Reputation: 44240

void *SignalCatcher(int n)
{
  wait3(NULL,WNOHANG,NULL);
}

Should be:

void SignalCatcher(int signum)
{
  wait3(NULL,WNOHANG,NULL);
}

The return type is very critical in a signal handler (because the calling convention is different from a normal function call). In any case, the compiler should at least have issued a warning.

Second: in the loop, you should handle error returns from recvfrom(). (and write() )

for(;;) {
        n = recvfrom(connfd,mesg,1000,0,(struct sockaddr*)&cliaddr,&clilen);
        if (n == -1 && errno = EAGAIN) continue;
        else if (n == 0) break; // for non-blocking sockets...
        write(connfd , "" , 1);
        mesg[n] = 0;
        printf("Received the following: %s\n", mesg);
     }

Upvotes: 1

William Pursell
William Pursell

Reputation: 212228

Why bother working so hard? Just daemonize the children as soon as they start (eg, fork twice with the first child immediately exiting while the grand-child continues with pid 1 as its parent.) Unless there is a reason to remain the parent of the worker processes, this will simplify things greatly.

Upvotes: 0

Related Questions