1:1 소켓 서버에서 반복적으로 소켓 열고 닫을때 이상 종료
안녕하세요?
Client와 1:1로만 통신하는 소켓 서버 프로그램을 소소들을 짜집기해서 만들었습니다.
기본 동작은 잘하는데 서버 테스트용으로 분간격으로 서버에 재접속하는 프로그램이 있습니다. 이녀석을
이용해서 반복 테스트를 해보면 3시간 정도 지나면 errnum = 1(operation not permitted)가 뜨면서
서버 프로그램이 죽습니다. 검토를 해봤는데 원인을 딱히 못찼겠네요.
linux kernel 2.4.1을 사용중입니다.
소스는 아래 첨부했습니다. 소켓옵션은 reuseaddr 및 keep alive time 옵션만 줬습니다.
초보라 원인 찾는데 뭐가 틀렸는지를 모르니 죽겠습니다. ㅜ.ㅜ
의견좀 부탁드립니다.
pthread_mutex_lock(&lan_handle_mutex);
LAN_HANDLE = -1;
pthread_mutex_unlock(&lan_handle_mutex);
res = listen(LAN_SOCKET_FD, 5);
if(res < 0)
{
PRINT_ERR(res, "LAN_SOCKET_LISTEN ERR");
exit(1);
}
while(1)
{
pthread_mutex_unlock(&lan_handle_mutex);
FD_ZERO(&readfds);
FD_SET(LAN_SOCKET_FD, &readfds);
if(LAN_HANDLE == 1)
FD_SET(LAN_CLIENT_FD, &readfds);
pthread_mutex_unlock(&lan_handle_mutex);
testfds = readfds;
result = select(FD_SETSIZE, &testfds, (fd_set *)NULL, (fd_set *)NULL, (struct timeval *)0);
for(fd = 0 ; fd <= FD_SETSIZE ; fd++)
{
if(FD_ISSET(fd, &testfds))
{
if(fd == LAN_SOCKET_FD) // client에서 socket 접속 요구가 들어오면...
{
client_len = sizeof(client_address);
client_sockfd = accept(LAN_SOCKET_FD, (struct sockaddr *)&client_address,
&client_len);
if(client_sockfd > 0)
{
pthread_mutex_lock(&lan_handle_mutex);
res = getpeername(client_sockfd, (struct sockaddr *)&client_address,&client_len);
if(res<0)
{
PRINT_ERR(res, "GET PEER NAME ERR");
close(client_sockfd);
pthread_mutex_unlock(&lan_handle_mutex);
}
if(client_address.sin_addr.s_addr != wallpad_ipAddr)
{
PRINT("WRONG TCP/IP WALLPAD CLIENT %d: %s",client_sockfd, inet_ntoa(client_address.sin_addr));
// IP FILTERING
close(client_sockfd);
pthread_mutex_unlock(&lan_handle_mutex);
}
else
{
if(LAN_HANDLE > 0)
{
close(LAN_CLIENT_FD); // 이전 Connnection Close
}
LAN_HANDLE = 1;
LAN_CLIENT_FD = client_sockfd;
FD_ZERO(&readfds);
FD_SET(LAN_SOCKET_FD, &readfds);
FD_SET(LAN_CLIENT_FD, &readfds);
pthread_mutex_unlock(&lan_handle_mutex);
PRINT("TCP/IP HA CLIENT ADDED");
addrl = inet_ntoa(client_address.sin_addr);
printf("HA IPaddr : %s\n", addrl);
f_ha_gas_request = 1;
f_ha_gas_alarm = 1;
// gas 상태 요청
t_data.length = FIXED_CPSG_DATA;
MAKE_CPSG_DEV_REQUEST(t_data.buff, DEV_TYPE_GAS);
LIST_ADD(RS232_CPSG, t_data);
// HA 상태 요청
t_data.length = HA_PACKET_LEN;
MAKE_WALLPAD_ST_REQUEST(t_data.buff);
LIST_ADD(WALLPAD, t_data);
}
}
else
{
PRINT_ERRNO("IF(FD==LAN_CLIENT_FD) BUT SOME WRONG");
// handle err
}
}
// Disconnect or Receive Data
else if(fd == LAN_CLIENT_FD) // HA Client로 부터 Data 수신됐을때..
{
pthread_mutex_lock(&lan_handle_mutex);
if(LAN_HANDLE == 1)
{
pthread_mutex_unlock(&lan_handle_mutex);
// check buff is available
if(ioctl(fd, FIONREAD, &nread) < 0) // ioctl function call error
{
PRINT("SOME WRONG");
// handle err
}
else
{
if(nread == 0)
{
// PRINT("DISCONNECTED");
pthread_mutex_lock(&lan_handle_mutex);
LAN_HANDLE = -1;
pthread_mutex_unlock(&lan_handle_mutex);
close(fd);
FD_CLR(fd, &readfds);
PRINT("REMOVE HA CLIENT");
}
else
{
memset(rx_buff, 0x00, ETHER_CLIENT_RCV_BUFF);
nread = READ_CLIENT_SOCKET(fd, rx_buff);
if(nread < 0)
{
pthread_mutex_lock(&lan_handle_mutex);
LAN_HANDLE = -1;
pthread_mutex_unlock(&lan_handle_mutex);
close(fd);
FD_CLR(fd, &readfds);
PRINT("IN CLIENT READ ROUTINE : REMOVE CLIENT");
}
else
{
if((nread == 6)||(nread == 7)||(nread == HA_PACKET_LEN))
LAN_DATA_PROCESS(fd,rx_buff, nread);
else
{
// FD_ZERO(&readfds);
// pthread_mutex_lock(&lan_handle_mutex);
// FD_SET(LAN_SOCKET_FD, &readfds);
// FD_SET(LAN_CLIENT_FD, &readfds);
// pthread_mutex_unlock(&lan_handle_mutex);
PRINT(" IN CLIENT READ ROUTINE : WRONG SIZE DATA ARRIVED");
}
}
} // end of else(nread == 0)
} // end of else(ioctl < 0)
}
else
{
pthread_mutex_unlock(&lan_handle_mutex);
} // end of if(LAN_HANDLE == 1)
} // end of if(fd = LAN_CLIENT_FD)
if(result < 0)
{
// handle err ...
PRINT_ERRNO("LAN SELECT FUNCTION ERROR");
FD_ZERO(&readfds);
pthread_mutex_lock(&lan_handle_mutex);
FD_SET(LAN_SOCKET_FD, &readfds);
if(LAN_HANDLE == 1)
FD_SET(LAN_CLIENT_FD, &readfds);
pthread_mutex_unlock(&lan_handle_mutex);
}
} // end of if(FD_ISSET..)
} // end of for(fd .. )
} // end of while
자문 자답이네요..
해당 소켓에 데이터를 쓸때 유효한 FD인지를 체크를 하니 죽는 증상이 사라지네요.
무식하게 signal(SIGPIPE, SIG_IGN)해도 잘 동작하지만 ....
하지만 단지 소켓을 열고 닫음을 반복할뿐이고 연결돼 있을때만 데이터를 씁니다.
근데 왜 FD가 틀린 순간 데이터가 써지는건지 모르겠네요..전부 mutex로 막아놨는데요.
요건 몰르겠어요..ㅠ.ㅠ
댓글 달기