By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
428,590 Members | 663 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 428,590 IT Pros & Developers. It's quick & easy.

Threads don't seem to be cleaned up

jlm699
100+
P: 314
Greetings all,

I have this server (running on Linux 2.6.17-gentoo-r9) that I've been tinkering with and I attempted to do a multi-threaded model to accept multiple connections, however I found that it was leaving zombie processes and not cleaning up after itself at all. The main thread was doing a waitpid((pid_t)-1, Null, WNOHANG) and keeping track of the number of clients it created/cleaned up. Since that did not work as I had expected I decided to try and allow only a single connection (ie, wait(NULL) causing the main thread to not listen for client connections until it cleaned up its child). While this works great and appears to clean up children when monitoring ps, when I watch 'top' it seems that used memory just constantly increases once the first client thread is spawned. After it is closed the used memory goes down a little, but then ever-so-slowly increases. If I remove the client threading all together the used memory does not fluctuate. Could somebody please peruse this threading model code I have posted below and tell me if I'm doing something blatently dumb?! I would greatly appreciate it!

Expand|Select|Wrap|Line Numbers
  1. int main(char argc, char *argv[])
  2. {
  3.     pid_t    pid;
  4.     pid_t    process_id;
  5.     struct    sigaction sa;
  6.     int    error;
  7.     int    sockfd;
  8.     int    ss_fd;
  9.     char    response[MAX_MSG_BUFF_SIZE];
  10.  
  11.  
  12.     sprintf(VersionString, "Daemon v %d.%d.%d", MajorVersion, 
  13.         MinorVersion, PatchVersion);                
  14.  
  15.     /* Spawn the daemon */
  16.     pid = fork();
  17.  
  18.     if (pid < 0) {
  19.         printf("Failed PID #0\n");
  20.         exit(EXIT_FAILURE);
  21.     }
  22.     else if (pid > 0) {
  23.         exit(EXIT_SUCCESS);
  24.     }
  25.  
  26.     sid = setsid();
  27.     if (sid < 0) {
  28.         printf("Failed SID\n");
  29.         exit(EXIT_FAILURE);
  30.     }
  31.  
  32.     /* Set up and install handler for signal SIGTERM */
  33.     memset(&sa, 0, sizeof(sa));
  34.     sa.sa_handler = &sigterm_handler;
  35.     sigemptyset(&sa.sa_mask);
  36.     sa.sa_flags = 0;
  37.     sigaction(SIGTERM, &sa, NULL);
  38.  
  39.     /* Set up and install handler for signal SIGINT */
  40.     memset(&sa, 0, sizeof(sa));
  41.     sa.sa_handler = &sigint_handler;
  42.     sigemptyset(&sa.sa_mask);
  43.     sa.sa_flags = 0;
  44.     sigaction(SIGINT, &sa, NULL);
  45.  
  46.     ss_fd = ds_open_server(DSTREAM_PORT);
  47.     if (ss_fd == -1) {
  48.         printf("ds_open_server socket error\n");
  49.         exit(1);
  50.     }
  51.  
  52.     while (!quit_daemon)
  53.     {
  54.         sockfd = 0;
  55.         if ((sockfd = ds_listen_for_client(ss_fd, BACKLOG)) > 0)
  56.         {
  57.             if (client_cnt > 5)
  58.             {
  59.                 strcpy(response, "MAX_CLIENTS");
  60.                 ds_send(sockfd, response, strlen(response));
  61.                 ds_close(sockfd);
  62.                 sleep(SLEEP_TIME);
  63.             }
  64.             else
  65.             {
  66.                 pid = fork();
  67.                 if (pid > 0)
  68.                 {
  69.                     client_cnt++;
  70.  
  71.                     while (client_cnt)
  72.                     {
  73.                         process_id = wait(NULL);
  74.                         /* This was causing zombie processes */
  75.                         //process_id = waitpid((pid_t) -1, NULL, WNOHANG); /* non-blocking wait */
  76.                         if (process_id < 0)
  77.                         {    /* waitpid error */
  78.                             perror("waitpid");
  79.                         }
  80.                         else if (process_id == 0)
  81.                         {    /* no zombies to wait on */
  82.                             break;
  83.                         }
  84.                         else
  85.                         {
  86.                             client_cnt--;
  87.                             //printf("Stopped child process %d\n", process_id);
  88.                         }
  89.                     }
  90.                 }
  91.                 else
  92.                 {
  93.                     if ((error = StartDataStreamer(sockfd)))
  94.                     {
  95.                         printf("Exiting with error = %d\n", error);
  96.                         StopDataStreamer();
  97.  
  98.                         exit(EXIT_FAILURE);
  99.                     }
  100.                     else
  101.                     {
  102.                         // printf("Datastreamer started successfully:  %d\n", sockfd);
  103.                         while (!quit_client)
  104.                         {
  105.                             // printf("sleeping client %d\n",sockfd);
  106.                             sleep(SLEEP_TIME);
  107.                         }
  108.                         exit(EXIT_SUCCESS);
  109.                     }    // end else
  110.                 }    // end else    
  111.             }    // end else
  112.         }    // end if
  113.     }    // end while
  114.  
  115.     ds_close_server(ss_fd);
  116.     exit(EXIT_SUCCESS);
  117. }    // end main
And by the way, the ds_* functions are just wrappers I made to simplify the amount of typing for sending/receiving/opening connections etc. And then StartDataStreamer is the actual code that does the work of transferring data back and forth from my other computer. StopDataStreamer just shuts everything down (raising quit_daemon). I don't see why this would cause a memory leak, and also if anybody has any idea why the original waitpid method was leaving zombies I'd love to hear your thoughts.

Thanks in advance!

James
Aug 9 '07 #1
Share this question for a faster answer!
Share on Google+

Post your reply

Sign in to post your reply or Sign up for a free account.