Как сохранить процесс от выхода при выходе из pthread? - PullRequest
2 голосов
/ 24 февраля 2009

Я пишу серверную программу на C, в которой каждый раз, когда клиент подключается, я создаю новую pthread для обработки запросов клиента.

Однако, когда все потоки завершаются, моя программа завершает работу, как если бы был выполнен вызов exit (). Это проблема - как мне ее преодолеть?

Допустим, сервер работает и подключено 2 клиента. Как только эти клиенты отключаются - и, таким образом, оба потока выходят - мой серверный процесс завершается. То, что я хочу, чтобы мой сервер продолжал принимать () запросы сокетов. Обычно это работает, когда я использую fork () и accept (). Что я делаю не так, что родительский процесс прерывается, а не зацикливается?

Код выглядит в основном так:

void *talker( void *d ) {
   int fd;
   char buf[] = "Hello client";

   fd = (int)d;

   while( 1 ) {
      write( fd, buf, strlen( buf )+1 );
      sleep(4);
   }
}


int main( int argc, char *argv[] ) { 

   pthread_t thread[50];

   int sockfd;
   struct sockaddr_in client_addr;
   int i = 0;
   int s1;

   /* ... other declarations */

  if (initialize_server_socket(portno, &sockfd) < 0) {
     fprintf(stderr, "Could not initialize socket\n");
     exit(-1);
  }   

  while( 1 ) { 
     s1 = accept( sockfd, (struct sockaddr *)&client_addr, &n );
     pthread_create( &(thread[i++]), NULL, talker, (void *)s1 );
  }   

  return(0);
}

Кроме того: это тот же проект из вопроса, который я уже задавал (ссылка приведена ниже) ... хотя, потратив слишком много времени на попытки безуспешно использовать select () и IPC, я решил, что из-за простота общего адресного пространства.

Использование каналов в C для IPC родитель-потомок делает программный блок

Кроме того, большая часть этого кода была взята отсюда: http://www.s5h.net/2006/06/27/pthread-socket-server-in-c/

1 Ответ

3 голосов
/ 24 февраля 2009

Если вы отладите его в gdb, вы увидите, что вы получаете SIGPIPE, который ваша программа не обрабатывает. Вы можете установить обработчик SIGPIPE или проигнорировать SIGPIPE.

Причина в том, что ваш поток пишет в сокет (канал), который был закрыт (клиентом), что вызывает SIGPIPE. Вы должны проверить возвращаемое значение write() после игнорирования SIGPIPE:

signal(SIGPIPE, SIG_IGN);

или ручку SIGPIPE. Это не имеет ничего общего с подключением двух клиентов. Если вы подождете 4 секунды после отключения клиента, вы получите SIGPIPE (в вашем случае).

...