소켓 통신에서 서버 좀비 및 프로세스 처리 문제
글쓴이: boardholic / 작성시간: 목, 2008/10/09 - 11:23오전
기존 소스를 약간 수정하여
간단한 게임서버로 사용중 시간이 갈수록(서버 접속횟수가 늘어날수록)
이상하게 메인 프로세스 외에 기타 프로세스들이 생성이 되어있습니다.
S, Ss등등 Z(좀비)는 아닌것 같은데 무슨 문제인지 잘 모르겠네요.
아래 소스를 한번 봐주시기 바랍니다.
#include 함수들 생략 ...
//함수선언
void sigchld_handle(int num);
int wait_child(int pid);
void insert_chld (int childid);
int init_server(short port);
int reinit_server(short port);
int get_connection(short port);
#define MAXPIDSIZE 1000
static int chld_pid[MAXPIDSIZE];//자식프로세스 아이디 저장
static int listensockd; //서버소켓
int receivePktSize;//받은패킷 사이즈
int main()
{
int result_sock;
int childid;
int status;
int i;
char tmpBuf;
int ret;
struct sigaction act, oact;
Log("server start try");
if ((childid=fork()) == -1) {
perror("first fork failed");
return;
}
else if (childid != 0)
return;
/* act.sa_handler = sigchld_handle; */
/* sigemptyset (&act.sa_mask); */
/* act.sa_flags = 0; */
/* act.sa_flags |= SA_RESTART; */
/* sigaction (SIGCHLD, &act, &oact); */
signal(SIGCHLD, SIG_IGN);
memset (chld_pid, -1, sizeof(chld_pid));
/* init_log(); */
init_server(10002);
Log("server started");
while(1) {
//접속한 클라이언트 소켓을 얻어온다.
if ((result_sock=get_connection(10002))==-1) {
Log("Connection Failed");
if (reinit_server(10002) == -1)
Log("Reinit Failed");
continue;
}
if ((childid=fork())==-1)
Log("Server Fork Failed"); //에러처리할것
else if (childid == 0) { //자식프로세스
Log("child (%d) started", getpid());
close(listensockd);//서버소켓 종료
setsid (); //데몬만들기
//표준입출력 닫기
close(0);
close(1);
close(2);
//데이터 송수신 처리
child_proc(result_sock);
break;
}
else { //부모프로세스
insert_chld (childid);
close(result_sock);//클라이언트소켓 종료
}
}
close(result_sock);
Log2("Connection Closed");
}signal(SIGCHLD, SIG_IGN)에서 좀비를 처리하는것같습니다.
전체적으로 문제가 될만한 곳이 있는지 어떤 부분에 의해 프로세스들이 종료가
안되고 생성되어 있는지 고수님들의 조언 부탁합니다.
Forums:


맞는 지는
맞는 지는 모르겠지만 waitpid 함수는 PID를 직접선택하여 기다리는 함수 입니다.
여기서 바로 종료 순서 문제가 나올 수 있겠네요...
예를 들어 5개의 프로세스를 만들었고 waitpid 함수를 사용한다고 한다면
처음 어떤 한개가 종료되기를 지정해 줘야 할것 입니다.
하지만 5개중 어떤게 먼저 종료 될지 알 수 없는 문제 입니다.
1번 프로세스를 wait 하고 있는데 3번 프로세스가 종료되 버리면
3번 프로세스는 바로 좀비가 되고 1번 프로세스를 계속 블럭킹 하면서 기달리는 현상이 발생할 것 같습니다.
waitpid 함수 부분을 wait 함수로 바꿔보시고 테스트를 해보시면 어떨까요.
wait 함수는 생성된 자식 프로세스들 중 어느하나가 종료되면 바로 리턴 됩니다.
물록 블럭킹 모드로 작동 됩니다.
아주쪼록 문제해결이 잘 되시길 바랍니다.
아 그리고 지금 보니
아 그리고 지금 보니 시그널을 받아서 종료 처리를 하고 계신데요.
이건 좋은 방법이 아닌듯 합니다.
프로세스가 어떠한 에러 때문에 종료될지 알 수 없기 때문에
( 종료된 파이프로 메시지를 보냈다던지...메모리 요류로 바로 종료되는 현상 등등 )
시그널로 처리 하는건 안정성에 문제가 되지 않을 까 십습니다.
이게 바로 signal-safe 라는 문제인데...
wait 함수를 지역함수로 빼서 처리를 하신듯 한데...제가 알기론
이 방법또한 그렇게 좋은 방법이 아닌걸로 알고 있습니다..
불필요한 소스 제거
답변 감사합니다^^
기존 sinal처리 함수들은 사용 안되고 있는 것들입니다.
signal(SIGCHLD, SIG_IGN)이 함수로 좀비처리는 될거같은데
원인을 잘 모르겠네요.
현재 실행중인 프로세스들이 존재할때의 상황을 제가 잘못 본거인지, 오랫동안 사라지지 않는걸
보면 그건 아닌것 같은데요. 좀더 확인해 보겠습니다.
나에게 있어 한계란 없다.
무한한 꿈을향해 나아간다.
아마도 제 예상이
아마도 제 예상이 맞을 것 같습니다. 저도 예전에 같은 문제로 고민한 적이 있었는데
wait 함수로 해결했었습니다.
wait 함수를 사용했음에도 좀비가 생긴다는 얘기는...
정확합니다. 좀비가 된 프로세스가 wait 함수에서 인식하지 못한 겁니다.
그리고 생성된 프로세스가 많으면 wait 를 여러번 돌려 주셔야 합니다.
wait 함수의 에러메시지를 보고 더이상 자식 프로세스가 있는지 없는지 여부도 알 수 있습니다.
그리고 프로세스가 종료 될때는 SIGCHLD 만 오는 것이 아닙니다. 그러므로 SIGCHLD 만을 이용하여
종료하는 것은 않됩니다. 정확히 에러마다 처리를 해주는 것이 바람직 합니다.
해보실 사항은 프로세스를 만드는 부모 프로세스에
int st; while( 1 ) { wait( &st ); }해보세요. 아마도 자신이 만든 모든 자식 프로세스가 제대로 종료될 것입니다.
댓글 달기