LINUX.ORG.RU

Бесконечный accept() вешает систему


0

1

UPD. Отбой, тема закрыта. Простая форк-бомба, ничего интересного :)

Внезапно обнаружил, что бесконечный вызов в цикле функции accept() вешает мою слакварь намертво.

Вот код сервера:

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

int main(int argc, char**argv)
{
	int listenfd,connfd,n;
	struct sockaddr_in servaddr,cliaddr;
	socklen_t clilen;
	pid_t     childpid;
	char mesg[1000];

	listenfd=socket(AF_INET,SOCK_STREAM,0);

	bzero(&servaddr,sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
	servaddr.sin_port=htons(32000);
	bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

	listen(listenfd,1024);

	for(;;) {
		//printf("Before accept\n");
		clilen=sizeof(cliaddr);
		connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
		if (connfd == -1) {
			//printf("Accept failed %s", strerror(errno));
			//break;
		}
		//printf("Accepted %s:%d!\n", inet_ntoa(cliaddr.sin_addr),
		//       (int)ntohs(cliaddr.sin_port));

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

			for(;;)
			{
				n = recvfrom(connfd,mesg,1000,0,(struct sockaddr *)&cliaddr,&clilen);
				if (n <= 0) { break; }
				sendto(connfd,mesg,n,0,(struct sockaddr *)&cliaddr,sizeof(cliaddr));

				printf("-------------------------------------------------------\n");
				mesg[n] = 0;
				printf("Received the following:\n");
				printf("%s",mesg);

				printf("-------------------------------------------------------\n");
			}

		}
		close(connfd);
	}
}

«Момент истины» наступает после того, как клиент аварийно завершил соединение с этим сервером. Соответственно, recvfrom() кидает ошибку BAD_FILE_DESCRIPTOR. А поскольку проверка ошибок (а именно - break) accept() закомментирована, то этот самый accept() вызывается бесконечное количество раз и система виснет.

Однако же, если раскомментировать printf'ы, то будет время успеть нажать ^C благодаря их относительной медлительности.

Собственно, вопрос: у кого этот же код приведет к зависанию?

Рецепт:

$ gcc tcp-server.c -o tcp-server
$ ./tcp-server

В другом окошке:

$ nc 127.0.0.1 32000
asd
^C
$ 

Не нашел ничего похожего по запросам «linux accept loop hang» и так далее.

★★

Последнее исправление: bk_ (всего исправлений: 1)

-            close (listenfd);
+//            close (listenfd);
anonymous
()

а зачем так много кода?

#include <unistd.h>
int main()
{
  while(1)
    fork();
}

anonymous
()

Да это же очевидно

Отбой, тема закрыта.

Решив проверить то же на Mac OS X, вдруг дошло, что это простая форк-бомба :)

Интересен тот факт, что для того, чтобы убить процесс

killall -9 tcp-server
, нужно породить процесс. А когда форк-бомба съела все, то ничего не поделаешь в обычной конфигурации.

bk_ ★★
() автор топика
Ответ на: Да это же очевидно от bk_

А когда форк-бомба съела все, то ничего не поделаешь в обычной конфигурации.

Если есть открытый шелл, то в нём можно сделать exec python =).

Deleted
()
Ответ на: Да это же очевидно от bk_

Я узнал много нового сейчас, почему у меня никогда не было проблем с сетью такого рода? :) Неужели fork такая опасная операция? Никогда ее не понимал и всячески избегаю.

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от anonymous

Ещё бы, её же не завезли в Windows

Спасибо, весомая причина её не использовать ;)

I-Love-Microsoft ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.