티스토리 뷰

블락 될수있는 시스템콜이 순서대로 동작하게끔 프로그램을 짜게 되면 문제가 발생할 확률이 존재한다.

위의 프로그램은 서버에 데이터를 보낼때 write를 두번에 나눠서 한다.

첫번째 write에서 서버 프로세스가 이미 종료되어서 RST메세지를 서버로부터 받게 되며

(그 메세지를 받기 위한 시간이 필요하므로 sleep(1)이 필요하다)

두번째 write로 RST된 클라이언트 커넥트 소켓에 한번더 write를 하게 될경우 SIGPIPE 시그널이 발생한다는것을 실험하기 위한 프로그램이다.


1. hi there를 입력할시 hi there가 정상적으로 서버로부터 에코됨.

2. 그 이후에(while문 한번 돌고 나서) 서버 자식 프로세스를 kill해봄.

3. 클라이언트는 서버로부터 FIN메세지를 받음.

4.그상태에서  Fgets를 통해 키보드로부터 입력을 받고, 첫번째 write를 실행해서 서버에 데이터를 1바이트만 보내봄.

5. 서버 자식 프로세스는 죽은 상태이므로 서버 커널은 클라이언트에게 리셋(RST)메세지를 전송함.

6.sleep(1)을 해주는 이유는 리셋 메세지를 받기 위한 시간을 벌기 위함이다.

7. 리셋 메세지를 받은 소켓에 다시한번 write를 하게 될 경우 SIGPIPE 시그널이 발생하며, -1을 리턴시키고 errno에 EPIPE를 설정한다.

적절히 처리해주지 않을 경우 디폴트 액션으로 프로세스 가 종료된다. 그러니까 프로세스 종료를 막기 위해서는 SIGPIPE시그널 핸들러를 설정 해주어야 한다.


=> 클라이언트의 경우에는 이런 SIGPIPE가 중요하지 않을수도 있지만 서버의 경우엔 치명적일수있다.

클라이언트가 종료 되고 나서 서버가 다시 데이터를 보내서 리셋메세지를 받았을때 다시 그 소켓에 데이터를 썼을때 서버 프로세스가 종료되어 버리기 때문에 서버 프로그램에서는 SIGPIPE 시그널을 적절히 처리해서(시그널 핸들러를 만듦)디폴트 액션인 종료가 발생하지 않도록 해야한다.


위의 사진에서 bye로 클라이언트로부터 리셋메세지를 받게 되며 클라이언트에서 그 리셋된 소켓에 한번더 write를 했기 때문에 Broken pipe라는 에러메세지가 출력된 것이다. 이 에러메세지가 출력 되기 위해서는 SIGPIPE 핸들러를 설정해 주어야 한다 그래야 디폴트 액션인 종료가 발동되지 않고, write의 리턴값을 이용해서 에러메세지를 출력해 줄 수 있다.




댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함