socket write 중......

wedwed의 이미지

os name - SunOS

서버 프로세스 하나당 클라이언트는 최대 100까지 수용할 수 있도록 짜놓았습니다.
현재는 20개 정도 접속해 있구요.

문제는 다른 때에는 정상적으로 잘 동작하다가
간혹.. (2~3일에 한번씩 쯤) 클라이언트로 패킷을 write하다가 죽어버립니다
패킷 길이는 30정도로 작습니다.

생길만한 signal들은 다 잡아 놓았고요...

core dumped 도 아니고, 에러가 리턴되는 것도 아닙니다..

그냥 write 하는 도중에 그 이상 아무런 로그도 찍지 못하고 죽어버립니다.

어떤 경우에 이런 상황이 발생할 수 있을까요...
프로그램 루틴상에 문제일지...
어떻게 에러를 잡을 수 있을지...

혹시라도 이런 경우 있으셨던 분이나 예상되는 문제 있으신 분은
꼭 답변 부탁드립니다. :cry:

bugiii의 이미지

SIGPIPE 알아보시구요. 막으시면 됩니다. 여기 게시판도 검색해보시구요.

wedwed의 이미지

웬만한 signal들은 다 추가시켜 놨어요...
sigpipe도 물론이고요....

- .. - ;;

monac의 이미지

아무런 로그도 못찍고 죽었는데 어떻게 write 시점인걸 아셨나요? 그렇게 비정기적으로 가끔 죽으면 서버의 다른 부분에서 죽었을 가능성은 없습니까?

그리고 죽었는데 core dump가 없다면
1. core dump가 안생기도록 설정이 되어 있거나
2. 죽은게 아니라 어떤 로직에 의해 exit 한게 아닌가...

답은 아니지만 같이 해결하자는 차원에서 적어봅니다.

bugiii의 이미지

생길만한 signal들이 무엇이고 잡아 놓은 것이 해당 시그널을 무시한다는 것인지요?

정말 날짜 write 함수의 리턴값조차 확인하지 못하는지요?

p.s. 아마도 write 하기전에 로그하고 한후에 로그해서 알아내신게 아닐까 합니다...

wedwed의 이미지

write바로 전에 로그를 찍었고요.
write함수에서 뭔가가 리턴되었다면.. (에러든지 성공이던지) 그에 맞는 로그를 찍었을 겁니다..

그런데 지금 로그상에서는 write함수 호출 뒤에 아무런 것도 안 보이네요..
그래서 저는 write호출 과정에서 문제가 생긴걸로 봤거든요..

wedwed의 이미지

core dump는 설정되어 있구요....
signal들은 잡히면 특정한 로그를 찍도록 함수를 호출시켜 놓았습니다.

위엣 분 말씀대로 write 리턴값 반환이 안됩니다...

bugiii의 이미지

시그널 무시하고 해보시기 바랍니다. 시그널 처리 함수 안에서 문제가 생기는 경우가 꽤 있습니다.

시그널 처리 함수 안에서 안전하게 사용할 수 있는 함수도 정해져 있으니까요. 집중적으로 살펴보심이...

moonzoo의 이미지

write호출하고 리턴값 처리 하는 루틴조차 타지 못하고 죽었다면

99.99% SIGNAL이 발생되었을 것이라 생각됩니다.

SIGNAL 처리 부분을 점검해 보시는 것이 좋을 듯 합니다.

mach의 이미지

wedwed wrote:
os name - SunOS

서버 프로세스 하나당 클라이언트는 최대 100까지 수용할 수 있도록 짜놓았습니다.
현재는 20개 정도 접속해 있구요.

문제는 다른 때에는 정상적으로 잘 동작하다가
간혹.. (2~3일에 한번씩 쯤) 클라이언트로 패킷을 write하다가 죽어버립니다
패킷 길이는 30정도로 작습니다.

생길만한 signal들은 다 잡아 놓았고요...

core dumped 도 아니고, 에러가 리턴되는 것도 아닙니다..

그냥 write 하는 도중에 그 이상 아무런 로그도 찍지 못하고 죽어버립니다.

어떤 경우에 이런 상황이 발생할 수 있을까요...
프로그램 루틴상에 문제일지...
어떻게 에러를 잡을 수 있을지...

혹시라도 이런 경우 있으셨던 분이나 예상되는 문제 있으신 분은
꼭 답변 부탁드립니다. :cry:


클라이언트가 서버에 항상 접속해 있는 상황인가요?
클라이언트 개수는 고정적인 유형인가요?
클라이언트가 서버에게 수집된 정보를 전송하는 유형인가요?
아니면, 서버가 클라이언트에게 주기적으로 무엇인가를 보내주는 유형인가요?
스무고개, 이제 시작하겠군요.
업무상 비밀사항을 제외하고라도, 대략적인 시나리오라도 써주시면 좋겠군요.
이대로 가면, 질문이 스무고개 이상은 진행되어야 알 수 있을듯합니다. :(
** 2-3일에 한번씩 죽는다면 원인은 다른곳에 있을 수도 있습니다.
** 심지어 프로토콜 포맷도 고려대상입니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

wedwed의 이미지

클라이언트와 서버는 항상 접속되어 있습니다.
새 접속이 들어올 때마다 인증하고 추가시킵니다.

서버는 내부 프로세스로부터 받은 데이터를 일정하지는 않지만 비율적으로 거의 일정한 양의 데이터를 클라이언트로 전송하고요...

클라이언트로부터 요청이 오면 거의 일정한 포멧의 패킷을 응답으로 줍니다..

지금은 클라이언트로 주는 일정한 포멧을 write할 때 문제가 생기구요..

그리고 같은 프로세스를 5개 정도 띄워놓고 있는데요
다른 프로세스에는 접속되어 있는 클라이언트가 많질 않거든요

유독 20개 이상인 프로세스에서만 이런 현상이 자주 일어나는데
이 현상과 관련이 있을지.....

최종호의 이미지

음..

일단 시그널에 의해서 죽는지, 아니면 로직상에서 종료하게 하는지 알아보기 위해서

쉘이나 C 프로그램, 또는 노가다로 해당 프로세스에 모든 종류의 시그널을 한번씩 다 쏴 보시고,

atexit() 을 사용해서 정상종료시에 로그를 생성한다든지 파일을 만든다든지 해서

정상적인 과정(exit이나 main return)을 통해서 종료된다는 것을 표시할 수 있는 흔적을 남겨보시기 바랍니다.

그리고 SIGABRT를 제외한 signal 핸들러 들이랑 atexit() 에서

abort() 등을 사용해서 강제적으로 코어파일을 만들도록 코드를 변경해 보시고요.

wedwed의 이미지

답변 감사합니다...

우선 그렇게 추가시켜놓고 더 살펴봐야 겠네요....

metalwolf의 이미지

시그널을 처리하셨다면 다른 문제일 유형도 있습니다.

만약 write block 상태를 서버가 죽었다고 착각 하실수 있으니까요.

write 하다가 blocking 당하면 딱 서버 먹통됩니다.

풀리는 타임도 굉장히 길죠.. 저 같은 경우는 3~4분이면 풀린다고

생각되는데도. 더 오래가는 경우도 많더라구요. ㅠ.ㅠ

위에 말씀이 너무 애매모호해서 그것 부터 정확하게 알려주시는게 답변을

해드리는데 편할수 있겠네요.

^____^; 방가여

wedwed의 이미지

block상태는 아니고요.. 죽어서 ps로 안 잡힙니다..

혹시나 해서 write blocking은 alarm으로 체크하고 있고요...

hey의 이미지

OS가 Sun OS라는게 걸리는데요.

전 써본 적은 없지만 KLDP 게시판에서 솔라리스는 패킷 크기가 4바이트 정렬되어 있지 않으면 문제가 생긴다는 글을 본 적이 있습니다.


----------------------------
May the F/OSS be with you..


hey의 이미지

2~3일에 한 번씩 죽으면 굉장히 답답하실 듯 .. ;


----------------------------
May the F/OSS be with you..


mach의 이미지

wedwed wrote:
클라이언트와 서버는 항상 접속되어 있습니다.
새 접속이 들어올 때마다 인증하고 추가시킵니다.

이미 문제를 푸셨다면 다행이지만, 아니라면 다음을 테스트해보시기 바랍니다.

1) 접속시에 클라이언트와 접속된 socket descriptor를 출력해 보시기 바랍니다.
물론, 로그파일, 또는 임의의 파일 등에 해야겠지요.

2) fcntl( sockfd, F_GETFL,.....)을 실행하여 현재 파일의(소켓) 상태를 검사한후
write()를 호출하도록 루틴을 바꿔보십시요.

3) 질문하신분도 답답하겠지만, 문제가 아직도 모호합니다요. :(
어떤 작업을 하는지 시나리오를 쭉 써주셔도 될듯한데요.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

wedwed의 이미지

지금 현재는 자꾸 죽으면 안되니까 fork해서 계속 다시 띄워지도록 해 놓았구요..

위에서 말씀하신 것처럼 atexit 처리도 해 놓았고,
그 밖에도 원인 파악을 위한 루틴들을 추가시켜 놓은 상태입니다..

그런데 아직까지 죽질 않아서.... - .. - ;;
좀 더 지켜봐야겠네요...

wedwed의 이미지

지금 확인해보니 client로 붙는 쪽 프로세스가 비정상적으로 제대로 close를 호출하지 못하고 죽는다고 합니다.
죽은 시간은 확인이 어렵다고 하시네요.. - .. - ;;

궁금한 게 있는데요....

socket 연결에서 상대편 프로세스가 어떤 오류로 비정상적 종료를 했다면 어떤 신호를 받을 수 있을까요... SIGPIPE신호가 잡히는 게 아닌가요...

그리고 만약 그 신호를 잡지 못할 경우에는 write가 어느시점까지 success될지...

어쨌든 원인은 확인된 것 같습니다.. :oops:

mach의 이미지

wedwed wrote:
지금 확인해보니 client로 붙는 쪽 프로세스가 비정상적으로 제대로 close를 호출하지 못하고 죽는다고 합니다.
죽은 시간은 확인이 어렵다고 하시네요.. - .. - ;;

궁금한 게 있는데요....

socket 연결에서 상대편 프로세스가 어떤 오류로 비정상적 종료를 했다면 어떤 신호를 받을 수 있을까요... SIGPIPE신호가 잡히는 게 아닌가요...

그리고 만약 그 신호를 잡지 못할 경우에는 write가 어느시점까지 success될지...

어쨌든 원인은 확인된 것 같습니다.. :oops:

SIGPIPE는 상대가 연결을 끊을때가 아니라, 끊긴 이후 write()를 호출할때, 발생합니다.
그래서 SIGPIPE에 대한 시그널핸들러가 이에 대한 대처를 하거나,
단순히 무시해버렸다면(SIGIGN), errno == EPIPE에 대해서 처리를 해보세요.

ret = write();
if (  ret == -1 ) {
   switch ( errno ) {
        case EPIPE :
               printf("클라이언트가 갑자기(?) 연결종료함\n");
               // 해당 클라이언트 소켓 닫고
               // 해당 클라이언트를 위한 자료구조가 있다면 이를 해제
               // 로그를 남기고 계속진행
         case ......
   }
}

대략 위와 같은 코드가 될것 같습니다.

*참고
heart beat: 주기적으로 클라이언트와 서버의 생존을 검사하는 패켓을 주고 받는 방법이 있습니다.
응용수준에서 작성할 수 있겠지요. 그외, setsockopt()로 SO_KEEPALIVE를
사용하는 방법도 있겠군요.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

wedwed의 이미지

우선 답변 감사합니다...

SIGPIPE신호는 특정 함수를 통과하도록 설정해놓았는데요..

그 함수를 타기 전에 죽어버렸는지... 아니면
SIGPIPE말고 또 다른 원인이 있는지는 모르겠네요..

아무튼 그쪽 프로세스가 죽으면 저희쪽에서는 SIGPIPE 를 잡는 수 밖에는 없을까요... - .. - ;;

여태까지의 상황을 보면 그 신호를 정상적으로 잡지 못하고
계속 write하다가(어디까지 정상적으로 보내졌는지 모름) 함수리턴도 못하고 죽어버렸었거든요..

그쪽 프로세스가 어느 시점에서 죽는지도 그에 따라 상황이 달라질 수 있지 않을까요?

write하기 전에 죽는다던지 write하는 도중에 죽는다던지... 요..

heart beat은 그쪽이랑 협의를 통해서 결정해야 할 것 같네요....

mach의 이미지

wedwed wrote:
우선 답변 감사합니다...

SIGPIPE신호는 특정 함수를 통과하도록 설정해놓았는데요..

만일 다음과 같은 형태라면,
signal(SIGPIPE, handlerFunction);

handlerFunction() 함수의 내부를 보여주세요.
그 부분이 조금 의심스럽습니다.(또한 이부분은 비즈니스로직과 관계없어서 보여주셔도 될듯합니다)

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

최종호의 이미지

wedwed wrote:
우선 답변 감사합니다...

SIGPIPE신호는 특정 함수를 통과하도록 설정해놓았는데요..

그 함수를 타기 전에 죽어버렸는지... 아니면
SIGPIPE말고 또 다른 원인이 있는지는 모르겠네요..

아무튼 그쪽 프로세스가 죽으면 저희쪽에서는 SIGPIPE 를 잡는 수 밖에는 없을까요... - .. - ;;

여태까지의 상황을 보면 그 신호를 정상적으로 잡지 못하고
계속 write하다가(어디까지 정상적으로 보내졌는지 모름) 함수리턴도 못하고 죽어버렸었거든요..

그쪽 프로세스가 어느 시점에서 죽는지도 그에 따라 상황이 달라질 수 있지 않을까요?

write하기 전에 죽는다던지 write하는 도중에 죽는다던지... 요..

heart beat은 그쪽이랑 협의를 통해서 결정해야 할 것 같네요....

음.. 혹시 시그널 핸들러 설정하실 때

signal(SIGPIPE, sigpipe_handler);

방식으로 설정하지 않으셨나요?

Solaris는 signal 이 기본으로 unreliable 했던 것 같거든요.

시그널 핸들러를 설정했는데도 아무런 출력없이 죽는다는 것은,

아마 시그널을 한번 맞아서 signal 설정이 풀린 후에

다시 시그널을 맞아서 그런 것이 아닌가 생각됩니다.

프로그램 로그에 SIGPIPE 맞았다는 게 하나 있지 않나요?

혹시 해당 프로세스로 각종 시그널 날리는 것은 해 보셨는지요?

동일 시그널 두번씩 날려보세요.

상대방에서 일방적으로 소켓종료를 했을 경우에 어떻게 해야하는지는

몇번 스레드에서 얘기가 됐던 것 같은데, 한번 검색해 보시기 바랍니다.

wedwed의 이미지

이제야 확실히 알 것 같아요... :roll:

signal 함수는 두번이상의 처리를 하지 못하네요..
sigaction으로 고치고 나니 괜찮습니다...

클라이언트의 연결 종료에 관해서 대책은 좀 더 살펴봐야 할 것 같구요..

답변들 감사합니다..~ :)

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.