소켓에서 select 에러 해결방법은?
소켓서버를 만들고 있습니다.
서버는 클라이언트 요청시에 자식을 fork 시키고
자식프로세스는 DB를 읽어서 결과를 클라이언트에 돌려주고 exit합니다.
문제는 자식프로세스가 종료될 때 부모프로세스의 소켓 select 함수에 (-1)에러를 발생시킵니다.
이게 어떤 시그널인지, 어떻게 해결해야 할지 잘 모르겟습니다.
고수님들 도와주세요 ^^
소스가 제대로 안 올라가 첨부합니다.
void z_handler(int sig)
{
pid_t pid;
int rtn;
pid=waitpid(-1, &rtn, WNOHANG);
}
int main(int argc, char **argv)
{
...
/* 시그널 핸들러 등록 */
/* SIGCHLD */
chldact.sa_handler=z_handler;
sigemptyset(&chldact.sa_mask);
chldact.sa_flags=0;
c_state=sigaction(SIGCHLD, &chldact, 0);
if(c_state != 0){
exit(1);
}
if((sockfd=socket(PF_INET,SOCK_STREAM,0)) < 0) {
exit(1);
}
memset(&serv_addr,0x00,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portNum);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if((bind(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))) < 0){
close(sockfd);
shutdown(sockfd, 0);
exit(1);
}
if(listen(sockfd,5) == -1){
close(sockfd);
shutdown(sockfd, 0);
exit(1);
}
FD_ZERO(&reads);
FD_ZERO(&temps);
FD_SET(sockfd, &reads);
fd_max=sockfd;
while (1){
int fd;
int buf_len ;
int srtn;
char rcvBuf[BUFSIZE];
temps=reads;
timeout.tv_sec = 3;
timeout.tv_usec = 0;
srtn = select(fd_max+1, &temps, 0, 0, &timeout);
if(srtn < 0){
sleep(3);
continue;
}
for(fd=0; fd if(FD_ISSET(fd, &temps)){
if(fd==sockfd) {
cliLen = sizeof(cli_addr);
rcvfd = accept(sockfd,(struct sockaddr*)&cli_addr,&cliLen);
if ( rcvfd < 0 ) {
continue;
}
FD_SET(rcvfd, &reads);
if(fd_max < rcvfd)
fd_max = rcvfd;
}
else {
memset(rcvBuf ,0x00,sizeof(rcvBuf));
buf_len = read(fd, rcvBuf, BUFSIZE);
if(buf_len == 0){ /* 연결 종료 요청인 경우 */
/* 연결해제 : 실제로는 여기는 안탐 */
FD_CLR(fd, &reads);
close(fd);
}
else if(buf_len > 0){
if ((chldpid = fork()) < 0 ){
write_log("fork error\n");
close(fd);
continue;
}
if(chldpid == 0) {
close(sockfd);
childJob(fd, rcvBuf);
FD_CLR(fd, &reads);
close(fd);
exit(0);
}
else{ /* 부모 */
close(fd);
FD_CLR(fd, &reads);
}
}
}
}
} /* for */
} /* while */
}
첨부 | 파일 크기 |
---|---|
question.txt | 2.72 KB |
고수는
고수는 아닙니다만...
child process가 종료될 때는 SIGCLD(System V) 또는 SIGCHLD(POSIX) 시그널이 발생합니다. parent 쪽에서는 SIGCHLD에 대한 시그널 핸들러를 작성하고 그 안에서 wait() 함수를 호출해 줘야 합니다.
네 그부분은 이미 구현이 되엇습니다.
소스가 좀 부족한듯 싶어 원글을 다시 수정할게요
근데 여기 엄청 느린데,, 저만 그런가요? 다른 분들은 안 느리신가?
소스가 너무
소스가 너무 부분으로 올라와서 구조가 안보이는군요. BBCode 태그로 싸서 최소한 알아 볼 수 있는 부분까지 올려주시기 바랍니다.
이번에 수정하신 코드에서는 select가 보이지 않습니다. accept의 반환 핸들인 듯한 fd도 어디에서 초기화되는지 보이지 않는군요.
bbcode 라는 게 안되네요 ;;
일케 사용하는게 맞죠?
(되네욥,,)
어이없게도,, 여기서는 되고 본문에서는 안되네요 ㅜㅜ
에러 내용을 perror()로
에러 내용을 perror()로 출력 해보시고...
일단 정확한 진단이 필요 할듯 하네요.
그리고 child가 종료될 때 parent에서 다른 해줘야 할 행동은 없는지도 확인을...
<어떠한 역경에도 굴하지 않는 '하양 지훈'>
#include <com.h> <beer.h> <woman.h>
do { if (com) hacking(); if (money) drinking(); if (women) loving(); } while (1);
#include <com.h> <C2H5OH.h> <woman.h>
do { if (com) hacking(); if (money) drinking(); if (women) loving(); } while (1);
select 함수 FD_CLR
리눅스 네트웍 개발 (FA) /유비쿼터스 네트웍 하드웨어 개발 프로젝트 진행/인터넷을 통한 원격제어/
리눅스 베이스 FA 구현/초소형 무선랜 모듈개발 진행중/리눅스 웹 통합시스템 구축
select 함수는 FD_SET을 이용하여 속켓을 감시하도록 등록하여
사용합니다.
등록된 속켓에서 보내온 데이터가 감지되는 경우는 + 값을 리턴합니다.
그러나 select 함수에 등록된 속켓을 종료하게 되면 FD_CLR 클리어 시켜주어야 합니다.
클리어 시켜주는 것을 게을리하면 1024?? 이상으로 증가되면 에러가 발생할수 있습니다.
생각나는데로 적었습니다. 함수가 맞는지 ???
....
리눅스 네트웍 개발 (FA) /유비쿼터스 네트웍 하드웨어 개발 프로젝트 진행/인터넷을 통한 원격제어/
리눅스 베이스 FA 구현/초소형 무선랜 모듈개발 진행중/리눅스 웹 통합시스템 구축
올려주신
올려주신 부분만으로는 큰 문제가 없는 것 같습니다. (좀 보기 힘든 서버 구조인 것만은 틀림없는 것 같습니다만..) child 쪽에서 수행하는 작업 중에서 segment fault 같은 것을 일으킬 만한 것이 없는지 확인하시는 게 좋을 것 같습니다.
댓글 달기