솔라리스에서의 시그널 함수에 대해
글쓴이: ddoman / 작성시간: 금, 2004/03/05 - 2:37오후
동작 환경은 솔라리스 8 sparc 입니다.
아래 코드의 간단한 tcp server를 만들었습니다.
void sig_chld( int signo ) { pid_t pid; int stat; while( ( pid = waitpid( -1, &stat, WNOHANG ) ) > 0 ) printf( "child %d terminated\n", pid ); ; // signal( SIGCHLD, sig_chld ); return; } int main( int argc, char* argv[] ) { int listenfd, connfd; pid_t childpid; socklen_t clilen; struct sockaddr_in cliaddr, servaddr; 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( 9978 ); bind( listenfd, (struct sockaddr*)&servaddr, sizeof( servaddr ) ); listen( listenfd, 1024 ); signal( SIGCHLD, sig_chld ); for( ; ; ) { clilen = sizeof( cliaddr ); connfd = accept( listenfd, (struct sockaddr*)&cliaddr, &clilen ); if( (childpid = fork()) == 0 ) { close( listenfd ); printf( "connected from client!\n" ); exit(0); } close( connfd ); } }
다음은 클라이언트..
int main( int argc, char* argv[] ) { int sockfd; struct sockaddr_in servaddr; if( argc != 2 ) { printf( "usage : client IP_ADDR\n" ); exit(0); } sockfd = socket( AF_INET, SOCK_STREAM, 0 ); bzero( &servaddr, sizeof( servaddr ) ); servaddr.sin_family = AF_INET; servaddr.sin_port = htons( 9978 ); inet_pton( AF_INET, argv[1], &servaddr.sin_addr ); connect( sockfd, (struct sockaddr*)&servaddr, sizeof( servaddr ) ); }
평범한 tcp server/client 예제입니다만,
이상하게 sigchild signal이 정상적으로 오지않습니다.
server를 띄어놓고 client로 접속을 하면
첫번째 연결로 생성된 child process는 죽으면서 sig_chld핸들러가
실행이 됩니다만,
두번째 연결부터는 child가 죽더라도 sig_child 핸들러가 실행이
안되면서 좀비프로세스로 남습니다.
마치 한번 시그널 핸들러가 불리고 시그널 핸들러설정이 풀리는거 같아
sig_chld함수안에서 다시 signal( SIGCHLD, sig_chld );
를 호출 해주면 의도한대로 계속 계속 시그널이 잘 옵니다.(주석처리한부분)
리눅스에서 같은 코드로 컴파일하면
굳이 signal함수를 핸들러안에서 다시 호출해주지 않아도
계속 계속 잘 옵니다만, 솔라리스 8에서는 안되는 이유가 뭔가요?
아시는분 계시면 조언 부탁드립니다.
Forums:
유닉스 계열에 따라 조금 동작의 차이가 있기는 한데, 이미 해보신바와 같
유닉스 계열에 따라 조금 동작의 차이가 있기는 한데, 이미 해보신바와 같이 주석 처리하신 부분을 다시 되살리시는것이 정답입니다.
sigaction도 한번 고려해 보심이...
sigaction도 한번 고려해 보심이...
signal 대신에 sigset 함수를 사용하셔야 될 것 같네요.
signal 대신에 sigset 함수를 사용하셔야 될 것 같네요.
솔라리스는 특이하게 signal 함수는 시그널 처리 후, 다시 디폴트 핸들러로 다시 복귀시킵니다.
리눅스에서 같은 동작을 원하시면 sigset 함수를 쓰셔야 합니다.
아니면 sigaction 함수를 사용하셔서...
---------------------------------
< ACK and you shall receive. >
< ACK and you shall receive. >
댓글 달기