[C] Too many open files 에러가 발생하는 이유가 무엇일까요?

maindb의 이미지

간단한 소켓프로그램을 작성했습니다.
말이야 작성한 것이지 joinc 에서 99.99% 그대로 가져다
사용하고 있습니다.

이 데몬이 하는일은... 클라이언트가 데몬의 특정포트로 접속을
한 다음에 어떠한 문자열을 날리면 그 문자열을 받아들여 실행
하는 것입니다.

아래 소스코드의 예는 클라리언트가 접속하여
/home 이라는 문자열을 날리면 system() 으로
ls -al /home 을 실행한다는 예 입니다.(의미가 없더라도...)

작동은 잘 하는데 하루정도 지나면
Too many open files 에러가 납니다.
위 에러가 무엇을 뜻하는지는 잘 알고 있습니다.

그런데... 일단,
프로세스가 사용하는 파일 개수의 limit 에 문제가 걸린다면
어디에선가 제대로 close 를 못하는 것일 수도 있겠지만
어디서 문제가 있는지 모르겠습니다.

아래 소스코드 중에서
perror("Accept error : "); 부분에서 위와 같은
에러가 발생하고 있습니다.
한번 살펴봐 주시고 조언 부탁드리겠습니다.

#include <sys/types.h> 
#include <sys/stat.h> 
#include <sys/socket.h> 
#include <signal.h> 
#include <unistd.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main(int argc, char **argv)
{
    int server_sockfd, client_sockfd;
    int state, client_len;
    int pid;

    struct sockaddr_in clientaddr, serveraddr;

    char buf[255];
	char buffer[255];

    if (argc != 2)
    {
        exit(0);  
    } 

    state = 0;

    client_len = sizeof(clientaddr);
    
    if ((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket error : ");
        exit(0);
    } 
    bzero(&serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_port = htons(atoi(argv[1]));

    state = bind(server_sockfd , (struct sockaddr *)&serveraddr,
            sizeof(serveraddr));
    if (state == -1)
    {
        perror("bind error : ");
        exit(0);
    }
    
    state = listen(server_sockfd, 5);
    if (state == -1)
    {
        perror("listen error : ");
        exit(0);
    }
    
    signal(SIGCHLD, SIG_IGN);
    while(1)
    {
        client_sockfd = accept(server_sockfd, (struct sockaddr *)&clientaddr, &client_len);

        pid = fork();
        if (pid == 0) 
        {
            if (client_sockfd == -1)
               {
                perror("Accept error : ");
				close(client_sockfd);
                exit(0);
            }
            while(1)
            {
				usleep(1000);
                memset(buf, '\0', 255);
                if (read(client_sockfd, buf, 255) <= 0)
                {
                    close(client_sockfd);
                    exit(0);
                }

				sprintf(buffer, "ls -al %s", buf);
                system(buffer);
				memset(buf, '\0', 255);
				close(client_sockfd);
            }
			close(client_sockfd);
        }
        if (pid == -1)
        {
            perror("fork error : ");
			close(client_sockfd);
        }
    }
    close(client_sockfd);
}
Fe.head의 이미지

자식 프로세서에서.. 일을 다끝마친다음에 exit(0)을 하지 않는것 같은데..

이게 이유가 될지는 모르겠지만.. 필요합니다..

고작 블로킹 하나, 고작 25점 중에 1점, 고작 부활동
"만약 그 순간이 온다면 그때가 네가 배구에 빠지는 순간이야"

maindb의 이미지

만약 그렇다면... 어디에다가 exit(0) 을 집어 넣어야 할까요? ^^;;

nthroot의 이미지

}
close(client_sockfd);
}

괄호 안으로 넣어야 할것 같네요.

close(client_sockfd);
}
}

------식은이 처------
길이 끝나는 저기엔 아무 것도 없어요. 희망이고 나발이고 아무 것도 없어.

maindb의 이미지

윽 >.< 거기가 어디 부분 인가요?
그러고 보니.. 줄맞춤이 제대로 안되서.... ㅡㅡ;;
맨 아랫 부분 말씀하시는 건지요? ^^;

nthroot의 이미지

마지막에 두번째줄에 있는 close 를 보시면...
while 문 밖에 있어서 매번 연결이 되고 클로우즈를 하지 않습니다.

------식은이 처------
길이 끝나는 저기엔 아무 것도 없어요. 희망이고 나발이고 아무 것도 없어.

maindb의 이미지

조언 감사드립니다. ^^;

jasonlife의 이미지

맞는지 모르겠습니다만..

while 루프안에서
fork 하게되면 자식프로세스는 부모가 오픈한 file descriptor의 copy본을 가지게 됩니다. accept 해서 생성된 새로운 소켓은 현재 부모 프로세스도 가지고 있고, 자식프로세스도 가지고 있는것 같네요..

소스를 보면 자식프로세스에서는 일 처리를 한후 close를 하지만, 부모프로세스에서는 뒷처리를 하지 않아서 계속 오픈된 상태로 남게 되는거 같네요.. 윗분 말씀대로 while루프 맨 뒤에서 close하거나,

else if (pid > 0)
{
close(fd);
)
를 추가해 주시면 좀더 매끄러울것 같은디... 자식프로세스 일처리뒤에 exit해주어야 할꺼 같습니다.

=================================
Jason

You are never too old to do something smart
=================================

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.