[서버 프로그램 한달 운영하면 클라이언트가 접속 못하는 상태에 빠집니다.]
안녕하세요
Solaris 10 에서 C로 구현한 멀티쓸레드 TCP/IP 서버이며
혼자서 이래저래 자료도 찾아보고 공부도 하고 있지만 해결되지 않아 이렇게 글을 올리게 되었습니다.
서버 프로세스는 클라이언트가 접속하면 쓰레드를 한개 생성하고
쓰레드와 클라이언트가 패킷을 주고 받는 동안
로그파일을 하나 생성해서 주고 받는 패킷에 대한 내용을 작성합니다.
파일 포인터는 써야 할 내용이 있을때
열고, 쓰고, 닫는 로직으로 되어 있습니다.
그런데 이 서버를 약 한달 정도 운영하면 Hang-Up에 빠집니다. (core 없이 client 요청 못받는 상태)
쓰레드가 만드는 로그 파일이 생성은 되지만 사이즈가 0인 것들이 한 일주일 뒤부터 생기면서
한달 즈음 지나면 쓰레드가 생성 요청하는 모든 파일이 생성은 되지만 내용은 아무 내용이 없는 사이즈 0인 파일만 존재하는 것입니다.
서버가 시작되고 Hang에 빠지는 기간 동안 제가 파악하는 유일한 징조는
로그 파일에 fprintf 결과가 나타나지 않는다는 것입니다.
(pfiles로 보면 fd 정상, thread수 정상, socket state 정상, prstat정보 정상, cpu 점유 정상)
도대체 이유가 뭘까요.
소스 전체적으로 다시 리뷰를 하고 있습니다 (Reentrant 검토, 자원 반화검토 중)
하지만 원인을 찾기가 너무 어렵네요.
아래 로그 남기는 로직을 한번 검토 부탁드립니다.
FILE* _log_open_Statistics(char* fname) { FILE *fp = NULL; struct tm pt; time_t cur_time; time(&cur_time); localtime_r(&cur_time, &pt); sprintf(fname, "%sLog_Statistics_%04d%02d%02d.txt",g_gonf1.log_dir, pt.tm_year + 1900, pt.tm_mon + 1, pt.tm_mday); fp = fopen(fname, "ab+"); return fp; } void log_write_Statistics(unsigned char *str, int len) { FILE *fpStatistics = 0x00; char fname[1024] = {0x00,}; fpStatistics = _log_open_Statistics(fname); if(fpStatistics != 0x00) { fprintf(fpStatistics,"%s %d byte\n", str, len); fclose(fpStatistics); } }
감사합니다.
혹시 디스크 full은 아닌가요?
혹시 디스크 full은 아닌가요?
디스크는 정상입니다.
디스크는 정상입니다.
client 요청을 받지 못한다는 것으로 보아 혹시
client 요청을 받지 못한다는 것으로 보아 혹시 어딘가 fd leak 이 발생해서
해당 프로세스에서 더 이상 fd 를 받지 못하는 상황이 된 게 아닐까요?
pfiles로 찍은 내용을 보았는데 fd가 순차적으로
pfiles로 찍은 내용을 보았는데 fd가 순차적으로 쌓이는 현상은 없었습니다. 하지만 한번 더 확인해 봐야겠네요
노파심에
컴파일할 때는 -W -Wall 옵션 주고 하셨죠? (gcc가 아니면 컴파일 옵션이 다를 수도 있겠군요.)
fopen/fprintf/fclose 대신에 O_APPEND option 주고 open한 다음에 write, close를 쓰면 system call을 직접 부르니 로그가 좀 더 잘(?) 남을지도 모르겠습니다. 그렇게 하면 좀 더 원인을 파악하기 쉽지 않을까요?
추측..
조심스럽게 추측해봅니다.
혹시 스레드 안에 어딘가의 무한루프로 인해 스레드가 끝나지 않고 한 클라이언트에 점유된채로 남아있는건 아닐까요?
무한루프는 없고 최대 3분정도의 loop 가 도는
무한루프는 없고 최대 3분정도의 loop 가 도는 로직은 있습니다. 쓰레드 안에서 또다른 쓰레드를 생성시키는 것이 껄끄러워
그냥 둔 부분입니다.
파일 포인터가 안 닫힌 것은 아닐까요?
안 닫힌 파일 포인터가 있는 것은 아닐까요?
열린 파일포인터가 계속 늘어나다가 최대값에 도달해서 작동을 멈추는 것은 아닌지요?
-----
계속 모니터링 해봐야 될것 같네요.. 그래도 서버가
계속 모니터링 해봐야 될것 같네요.. 그래도 서버가 hang이 걸리는 정도라면 무언가가 눈에 띄게 쌓여 있어야 하는데 쌓여있는건 사이즈가 0인 파일들 뿐입니다.
저도 초보이지만 좀 적어보자면..
fopen() 같은 system call 이 항상 성공한다는 보장은 없으며,
system call 을 사용할 경우 실패시 errno 와 error string 을
꼭 디버그용도로 찍어두는게 중요하다고 봅니다.
fprintf 도 마찬가지고요,
multi-thread 라면 file write 시에 race condition 같은 것도 고려해야 할 것 같습니다.
이상 초보의 허접한 댓글이었습니다.
개별 쓰레드마다 파일 fp를 열어서
개별 쓰레드마다 파일 fp를 열어서 사용하시는건가요?
파일 fp를 전역으로 설정해서 공유하는 방식으로 하시면 될거 같아 보입니다.
/proc 밑에 프로세스 아이디로 들어가셔서 fd
/proc 밑에 프로세스 아이디로 들어가셔서 fd 같은거 조사해보세요.. 릭이 있지 않나...
제가 문제 해결하면 꼭 게시글 올리겠습니다. 먼저
제가 문제 해결하면 꼭 게시글 올리겠습니다.
먼저 io쪽 low level로 바꾸고 로그 찍어서 더 확인해 보겠습니다.
답변 감사드립니다.
댓글 달기