signal과 socket
글쓴이: hammer / 작성시간: 월, 2003/02/03 - 6:04오후
시그널 대기하는 sigprocmask를 써서 제가 짜고 있는
프로그램에 적용할려고 하니
에러가 나더군요. (accept부분에서 Interupted System call이라고..) 소켓 연결도 하지 않았는데 말입니다.
짤막한 저의 프로그램을 소스를 보여드리면..
int main() { int i = 0; struct sigaction intsig, usrsig; ......... ........ usrsig.sa_handler = sig_usr; sigemptyset(&usrsig.sa_mask); usrsig.sa_flags = 0; intsig.sa_handler = sig_int; sigemptyset(&intsig.sa_mask); intsig.sa_flags = 0; if (sigaction(SIGINT, &intsig, 0) == -1) { printf ("signal(SIGALRM) error"); return -1; } if (sigaction(SIGUSR2, &usrsig, 0) == -1) { printf ("signal(SIGUSR2) error"); return -1; } if ((tcp_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket "); exit(-errno); } memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(PORT); if (bind(tcp_fd, (struct sockaddr *)&server_addr,sizeof(server_addr)) < 0) { perror(" bind "); exit(-errno); } if (listen(tcp_fd, 1) < 0) { perror("listen "); exit(-errno); } for (;;) { conn_fd = accept(tcp_fd, (struct sockaddr *)&server_addr, &addr_size); if (conn_fd < 0) { perror("accept "); } server_comm(conn_fd); close(conn_fd); } } void sig_int(int signo) { sigset_t sigset, oldset; sigfillset(&sigset); if (sigprocmask(SIG_BLOCK, &sigset, &oldset) < 0) { printf("sigprocmask %d error \n", signo); } fprintf(stderr, "SIGINT !!!!\n"); sleep(5); } void sig_usr(int signo) { sigset_t sigset, oldset; sigfillset(&sigset); if (sigprocmask(SIG_BLOCK, &sigset, &oldset) < 0) { printf("sigprocmask %d error \n", signo); } fprintf(stderr, "SIGUSR2 !!!!\n"); sleep(5); }
이런식으로 되어있는데요.
시그널을 발생해서 하면 시그널 자체는 실행이 잘되는데
시그널을 마치고 올때 accept()부분에서 에러가 나더군요
왜그럴까요?
그리고 시그널을 대기하는 것처럼 socket연결도 시그널 수행중에 소켓연결을 시그널이 마칠때까지 기다린후 수행을하는 방법과 통신이 되는중에도 발생한 시그널을 대기시켜서 통신이 끝나면 시그널이 대기된것이 수행하는 방법이 있으면 가르쳐 주십시요
Forums:
시그널과 accept
안녕하세요.
우선 코드도 건성으로보고 답변을하는 저를 용서하십시오. 8)
문제는 아마 이럴 것입니다.
1. 시그널 S에 대한 핸들러 등록.
2. accept() 에서 블록 중.
3. S 발생!
4. S 핸들링하고 accept()로 반환.
5. accept()는 errno에 EINTR를 설정하고 -1을 반환.
님께서 올린 코드를 보면, accept()가 반환한 디스크립터가 -1이면 바로 perror()를 호출하게 되어있기때문에, 님께서 지적하신 에러메시지가 출력되는거라 사료됩니다. 그렇다면 그 위에 다음 코드를 추가해보면 어떨가 생각됩니다.
일단 errno.h를 포함하시고.
그럼. 즐거운 시간되세요~
"꿈이 있는 자는 흔들리지 않는다! "
[url]http://ldk.sarang.net [/url]
"꿈이 있는 자는 흔들리지 않는다! "
답변감사합니다. 그리고....
말씀하신되로 하닌깐 잘되네요..감사합니다.^^
다른 질문이 몇가지 있는데요.
sigprocmask를 이용해서 시그널이 오는 도중에 다른 시그널이 오면 대기했다가
마치고 나서 다른 시그널이 수행이 되는데요..
이 방법 말고 sa_mask를 이용해서 하는 방법이 있다고 하는데 이건 어떻게 사용해야 하는지 궁금합니다. 그리고 다른 예제들을 보니
sigfillset(&sigset);
if (sigprocmask(SIG_BLOCK, &sigset, &oldset) < 0) {
perror("sigprocmask ");
return;
}
시그널 루틴 끝나기 전에
if (sigprocmask(SIG_SETMASK, &oldset, NULL) < 0) {
perror("sigprocmask ");
return;
}
이런식으로 되어 있던데. 꼭 해줘야 하는지 알고싶습니다.
제 생각엔 예전 mask값으로 셋팅해주는거 가튼데..
그리고 이것처럼 socket통신중에 시그널이 오면 대기했다가 통신이 마치면 시그널이 수행되도록 할 수 있습니까?
그리고 시그널 도중에 accept에서 통신 연결이 되면 대기했다가 시그널이 끝나면
통신이 바로 수행할 수 있습니까?
만약되면..답변 부탁드리겠습니다.
그럼 수고하십시요.
좀 다른 이야기입니다만유닉스 시스템 프로그래밍할 때는 항상 이 시
좀 다른 이야기입니다만
유닉스 시스템 프로그래밍할 때는 항상 이 시그날을 염두에 두어야 하는 데, 어떤 시스템콜(open(), read(), write() ...) 을 사용하든 지 특별한 경우가 아니면 처음에 코딩할 때 부터 'if ( (콜==실패) && errno == EINTR)) 이면 다시' 부분을 추가해놓는 습관을 들이는 것이 좋다고 생각합니다.
안 하고 시스템콜을 수백군 데 해서 나뒀다가 나중에 10초마다의 타이머가 필요하다고 알람을 설치하는 등의 요구사항이 생기면 골치아파 질 것 같지요?
댓글 달기