Accept 에러 2
몇일전 똑같은 문제로 질문 올렸던 사람입니다.
조금 더 틀린게 있어서 다시 올립니다.
accept시 아래와 같은 에러가 계속적으로 발생 되나 클라이언트에서 접속을 요청하면 접속 요청을 제대로 받고 있습니다.
이게 정상인가요?
EINTR 에러가 OS에 따라서 같은 BLOCKING SOKET인데 발생됐다 안됐다 하나요?
이게 정상이라면 그냥 넘어갈려고 하는데 고수님들의 의견은 어떠신지 궁금합니다.
[14:29:22] Accept IP[0.0.0.0] nClientHandle[-1] EINTR LINE[979]
[14:29:23] Accept IP[0.0.0.0] nClientHandle[-1] EINTR LINE[979]
[14:29:24] Accept IP[0.0.0.0] nClientHandle[-1] EINTR LINE[979]
[14:29:25] Accept IP[0.0.0.0] nClientHandle[-1] EINTR LINE[979]
[14:29:26] Accept IP[0.0.0.0] nClientHandle[-1] EINTR LINE[979]
위의 증상처럼 시간대별로 틀리고 분명히 아무 옵션이 없이 아래와 같이 생성했으니 block소켓 아닌가요?
클라이언트가 준비가 안되어 있고 혼자 도는데 계속적으로 accept에러가 위와 같이 떨어지네요
g_ServerHandle = socket(PF_INET, SOCK_STREAM, 0);
setsockopt(g_ServerHandle, SOL_SOCKET, SO_REUSEADDR, (char *) &bf, (int) sizeof(bf));
memset(&g_stServerAddr, 0, sizeof(struct sockaddr));
g_stServerAddr.sin_family = AF_INET;
g_stServerAddr.sin_addr.s_addr=htonl(INADDR_ANY);
g_stServerAddr.sin_port=htons(SERVER_PORT);
g_stServerAddr.sin_len=sizeof(g_stServerAddr);
아래는 accept 소스입니다.
stClientAddr.sin_len = SIZE_SOCKADDR;
nClientHandle = (int)accept(g_ServerHandle, (struct sockaddr *)&stClientAddr, &addr_len);
부탁드립니다.
고수가 다 그만뒀나봅니다. ㅇ_ㅇ;;
언능 다른 방법을 강구해 보시기 바랍니다.
----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
EINTR은 blocking socket에서 더 잘
EINTR은 blocking socket에서 더 잘 납니다.
그리고 accept 부분만 떼서 테스트 해보셨나요? 지금 올린 것만 가지고는 누구도 답해줄수 없습니다.
Written By the Black Knight of Destruction
그렇군요 답변 감사하며 다각도로 검토중에 있습니다.
그렇군요 답변 감사하며 다각도로 검토중에 있는데요 이상한점을 찾긴 했습니다.
accept를 하고있는 프로세스 이름이 Aprc라고하고 그외 두개의 프로세스 Bprc와 Cprc가 있다면
Bprc는 kill( (pShmProcess+PRC_LCCOM)->nId, SIGUSR1); 라는 시그널을 1초에 한번씩 보내고
Cprc는 프로세스를 모든 프로세스를 종료할때 종료 시그널을 보내기 위해 kill( pProcess->nId, SIGTERM);
시그널을 보냅니다.
그리고 accept를 하는 Aprc 프로세스는
signal( SIGTERM, LcCom_ProcessExit );
signal( SIGUSR1, LcCom_SendIntStatusReq);
위의 두개 시그널을 받는데요 Bprc프로세스에 1초에 한번씩 보내는걸 주석처리하면 Accept에러가 안떨어지고 정상 동작 하네요 Accept에러는 1초에 한번씩 떨어지는걸로 봐서 시그널을 주고 받을때 문제인것 같은데요
그리고 최종적으로 프로세스 종료시킬때 Cprc가 보내는 한번의 시그널로 마지막에 Accept에러가 떨어지네요
설명이 주저리주저리 죄송한데 이 상태에 대해서 혹 아시는지요?
네, EINTR은 시그널 때리는 다른 프로세스들
네, EINTR은 시그널 때리는 다른 프로세스들 때문인거 맞습니다. systemcall이 원하는 만큼의 작업 마무리가 안되서 block인 상태에서 시그널 오면 하던거 멈추고 EINTR과 함께 리턴됩니다.
그런데 SIGTERM과 SIGUSR1,2로도 종료 안되는걸 보면 꽤 복잡한 프로그램으로 보이네요.
이들 시그널의 기본 핸들러는 "프로세스 종료"입니다. 종료 안됐다는거는 시그널 핸들러를 설정 했다는 얘깁니다.
거기다 EWOULDBLOCK/EAGAIN 까지 있다면 accept하는 프로세스의 내부 어딘가에서 조용히 nonblock 설정 했다는 얘기네요.
Written By the Black Knight of Destruction
죄송한데 제가 SIGTERM은 종료 시그널로 사용하고
죄송한데 제가 SIGTERM은 종료 시그널로 사용하고 있어서 문제 될게 없는데
SIGUSR1이 프로세스 종료라면 일반적으로 어떤 시그널을 사용하나요?
리눅스나 혹은 Sun 및 hp에선 잘 돌아가던 소스라서 의심을 하지 않고 있었는데요
왜 aix에서만 이러는지 몰라서요 다 그렇다면 이해를 하겠는데요 ㅠㅠ
추가 말씀드리면 죽지 않은 이유는
signal( SIGUSR1, SIG_IGN );
IntCmd_ReqIntStatus();
signal( SIGUSR1, LcCom_SendIntStatusReq );
위의 소스에서 처리하는 부분에 SIG_IGN으로 시그널을 무시해서 그런 것 같구요 ㅠㅠ
SIGUSR1,2는 원래 사용자가 맘대로 정의해서
SIGUSR1,2는 원래 사용자가 맘대로 정의해서 쓰라고 둔 시그널이지만, 기본 동작은 "종료"입니다. 핸들러 지정 안한 상태에서 이 시그널이 들어오면 SIGTERM과 똑같이 돌아간다는겁니다.
Written By the Black Knight of Destruction
제가 계속적으로 찾다 보니까 이런말이 있더군요
제가 계속적으로 찾다 보니까 이런말이 있더군요
레드헷이나 리눅스 6.0에서는 간단히 테스트해본결과 EINTR이 반환되지 않았다. 하지만 GNU C라이브러리 코드가 표준화되면서 개편되고 정제됨에 따라 이 상황은 달라 질 수있다.
만약 응요프로그램이 리눅스 이외의 다른 유닉스 플랫폼에서 실행해야 한다면 코드에서 EINTR을 테스트해보아야 한다.
만약 EINTR을 코드에서 처리해야 한다면 다음 코드와 같은 형태를 사용하면 된다.
do{
;
}while(ferror(%x) && error==EINTR);
즉 제 생각에는 OS에 따라서 발생될 수 있는 에러이며 꼭 문제로 생각 안하고 위와 같은 코드로 처리해도 무방하다고 생각하면 될런지요?
제가 위의 내용을 잘못 이해하고 있는지요?
넵
accept() 같은 어떤 일이 생길때까지 단순히 대기만 하는 시스템콜일경우 EINTR은 무시해도 됩니다.
Written By the Black Knight of Destruction
님과는 실시간 채팅을 하고 있는것 같아 정말
님과는 실시간 채팅을 하고 있는것 같아 정말 감사하네요
늦은 시간까지 친절한 답변 정말 감사합니다.
한번 테스트가 아닌 현업에 적용해 봐야 알 것 같네요
근데 제가 맡은 일이 적용했다가 잘못되면 큰일 나는 일이라서 걱정이네요 ㅠㅠ
다시한번 실시간 답변 감사합니다.
댓글 달기