2009-05-14 6 views
3

요청에 따라 소켓 연결을 수신하고 다른 종류의 작업을 수행하는 서버가 있습니다. 그 중 하나는 서버가 분기하는 데이터베이스 쿼리를 오래 보관했습니다.포크와 소켓을 사용할 때 비정상 종료 처리

서버는 모든 활성 하위 로그를 보관하며 시스템 종료를 요청할 때마다 종료되기 전에 모든 자식을 종료합니다. 몇 번 나는 서버가 추락하거나 비정상적으로 죽은 상황에 직면하여 자식 프로세스가 고아가되게했습니다. 서버를 다시 가져 오려고하면 해당 주소/포트가 이미 바인딩되어 있기 때문에 수신 대기 소켓을 바인딩 할 수 없다는 메시지가 거부됩니다.

이 상황을 개선 할 방법을 찾고 있는데, 주 ​​서버 프로세스가 즉시 복구 될 수 있습니다. 나는 아이로부터 부모 존재를 모니터링 해 보았고, 곧 사라지 자마자 나갔다. 그러나 이것은 단지 좀비 프로세스를 가져 왔고 소켓은 여전히 ​​묶여있는 것 같다.

서버는 파이썬으로 작성되었지만 모든 언어로 된 설명이나 제안은 환영합니다.

+0

서버 종료 방법을 알고 있습니까? 신호 처리기에서 문제를 발견 할 수 있다면 자식을 종료 할 수 있습니다. – Kekoa

+0

유닉스의 맛? – sigjuice

+0

하위 프로세스가 상위 프로세스와 종료 프로세스가 사라지는 것을 감지하고 있습니까? 부모가 사라지면 init (pid 1)은 자식 프로세스를 상속 받아야하며 종료 된 자식에 대해 wait()를 호출해야하며 좀비는 절대로 발생하지 않아야합니다. – sigjuice

답변

0

아마도 포크 할 때 부모 프로세스가 OS에 등록 된 부모가 아니도록 자식을 해제하십시오. 부모는 정말로 아이와 의사 소통을해야합니까? 그렇지 않은 경우 옵션이 될 수 있습니다.

하위 프로세스는 다른 방법으로 추적 할 수 있습니다. 더 이상 SIGCHLD 이벤트를받지 못합니다. 당신이 (들을 호출하기 전에 소켓

1

사용이) :

int on = 1; 
setsockopt (sockfd_wan, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)); 

심지어는 무작위로 포트 < 위해 (일어나지 않을 수있는 또 다른 나가는 TCP 접속에 의해 이전에 주웠다, 당신의 programm에 그 소켓을 사용할 수 있습니다 1024). 그러나 그것은 또한 당신의 문제에 직접적으로 도움이됩니다! 관련없는

:

일어날 수있는 또 다른 나쁜 일이있다 : 당신의 차일가 갈래의 경우, 그들은 열려있는 모든 FileDescriptor에 상속이. 그들이 단순히 오래 실행중인 다른 프로그램을 포크하고 실행하면 청취 소켓에 대한 열린 핸들도 있으므로 사용 상태로 유지됩니다 (lsof 및 netstat 명령으로 찾으십시오).

따라서

이 차일을 포크와는 명확하게 차일이 갈래 때문에, 임원과 실행되지 도움이되지 않을 경우
int close_on_exec_on(int fd) 
{ 
    return fcntl(fd, F_SETFD, FD_CLOEXEC); 
} 

close_on_exec_on(sockfd); 

는하지만 메인을 programm에서 그것을 시도하지 않았다.

그러나 명심하십시오. 어쨌든 주 프로그램의 청취 소켓에서 호출하십시오. 외부 프로그램을 실행할 경우를 대비하여

2

서버를 process group의 리더로 만듭니다. 이 경우 아이들은 그룹 리더가 퇴장 할 때 종료됩니다.

텍스트 기반 사용자 인터페이스가 유닉스 계열 시스템에서 사용되는 경우 세션은 로그인 세션을 구현하는 데 사용됩니다. 세션 리더 인 단일 프로세스는 사용자가 터미널 연결을 중단 할 때 모든 프로그램이 종료되도록하기 위해 제어 터미널과 상호 작용합니다. (세션 리더가없는 경우 터미널의 포 그라운드 프로세스 그룹의 프로세스는 중단을 처리 할 것으로 예상됩니다.)

관련 문제