read에서 멈춘 client process가 반응이 없습니다.

김경태의 이미지

질문 1:

client process는 server process에 connection 상태로 있으며 read에서
대기상태입니다.

이때 server process를 kill하면 보통의 경우 client process는 read에서
return하게 되어 있습니다.

그런데 무슨 이유인지 아무 일도 하지 않고 read에서 동작이 멈춰버린 프로세스
는 server가 kill되는데도 아무런 반응도 보이지 않습니다.

이런 경우는 주로 어떤 경우인지 참으로 궁금합니다.

질문 2:

어떤 프로세스의 pid와 프로그램 이름을 알고 있으며 그 프로세스가 connect
해야 하는 port number를 알고 있다고 가정합시다.

이 경우에 이 프로세스의 해당 포트에 대한 상태(ESTABLISHED, TIMEWATE
등)를 알고 싶은 경우 어떻게 해야지 이 정보를 알수 있을까요?

고수님들의 높으신 탁견을 기대합니다.

송동섭의 이미지

질문 1: 

client process는 server process에 connection 상태로 있으며 read에서 
대기상태입니다. 

이때 server process를 kill하면 보통의 경우 client process는 read에서 
return하게 되어 있습니다. 

그런데 무슨 이유인지 아무 일도 하지 않고 read에서 동작이 멈춰버린 프로세스 
는 server가 kill되는데도 아무런 반응도 보이지 않습니다. 

이 상황이 BROKEN PIPE 상황이 발생할 수 있는 조건이 아닐까요? 소켓 프로그램이라 하여도 연결성에 대해서는 보장한다고 생각하시면 않될듯 싶습니다.

위의 Server Process가 사라질때 ( 죽였을때 ) 특정 disconnect 메세지를 날리지 않는다면 Client에서 Server가 죽었다는것을 알거라 생각하시면 않될듯 생각 됩니다. 그래서 산업, 특수목적 등에 사용되는 프로토콜을 보면 주기적으로 상대방이 살아 있는지를 확인하는 폴링 메세지를 보내도록 고려되고 disconnect메세지를 날리도록 설계되는겁니다.

위의 프로그램에서 Client쪽에서 wirte하도록 하시고 ( Server에서 read ) 테스트를 해 보시면 위의 상황에서는 Server가 죽은 시점 이후로 write를 한번하는 시점에서도 이상이 없고 두번째 write하는 시점에서 BROKEN PIPE signal이 프로세서를 죽일거라 생각이 듭니다. 결국 위의 상황을 피하고 안정된 소켓 통신을 위해서는 Disconnect Msg, Polling Msg가 고려 되어야 합니다.

** Inside Of Inside By Forman

최종호의 이미지

간단하게 뼈대코드만 한번 올려봐 주시면 어때요?
말슴하신대로 서버쪽이 죽으면 client쪽에서는 read()가 0을 리턴하면서
block상태에서 빠져나와야 할 것 같은데 그러지 않았다면
뭔가 다른 이유가 있었을 것 같은 생각이 드는데요.

김경태의 이미지

아주 간단한...흔히 보는 코드입니다.

int my_readn(int fd, void *vptr, size_t n) {
    size_t  nleft;
    int nread;
    char    *ptr;

    ptr = (char *)vptr;
    nleft = n;

    while (nleft > 0) {
        if ( (nread = read(fd, ptr, nleft)) < 0) {
            if( errno == EINTR )
                nread = 0;
            else
                return (-1);
        }
        else if (nread == 0)
            return (0);

        nleft -= nread;
        ptr += nread;
    }
    return (n - nleft);
}
최종호의 이미지

아마 넷웍 문제가 아닐까요?
lsof 로 클라이언트 프로세스가 사용하고 있는 프로세스를 살펴보시면
소켓 디스크립터는 소켓상태에 대한정보가 나오니까 참고해 보세요.

lsof -p pid

송동섭의 이미지

위에서 제가 말씀드린것과 같이 문제가 아니라 프로그램상에서 당연히 고려 되어야 하는것입니다. 만약에 두 PC상에서의 통신에서 한쪽의 네트워크 선을 제거 하였을 경우는 어떻게 반응하게 될까요? 이런경우나 다른 한쪽의 프로세서가 하단 레이어에 자신의 죽음을 알리지 못할경우 등은 read()에서 모두 처리할 수 없는 것입니다.
write()를 통해서 테스트 해보싶시요.

** Inside Of Inside By Forman

김경태의 이미지

client 자신의 network line 뽑고 나서 log 발생 3번 그리고 network line 원
위치 후 log 발생 1번
-> 이경우 network line이 뽑힐때 발생한 log 3을 포함하여 netwokr line 원위치후 발생한 로그 1번까지 모두 recv됨.

이걸 보면 network error가 발생해도 이 함수가 모두 처리할 수 있다는 사실을
알수 있었습니다.

그렇다면 왜 저의 프로세스는 read 함수에서 멈춰 있을까요?

고수님들의 현명한 고견을 부탁드립니다.

송동섭의 이미지

우선 위의 read문을 보았을 때 readn 의 경우 select와 같이 사용하였을 듯 보이는데 그런가요? ( select로 데이터가 들어왔는지를 확인 후 read하는지, 실제 외부 소스 프로그램 상에서는 wrtie도 존재하는지? )

네트워크 선을 제거했을때 log라는게 무슨 log를 의미하는지??

** Inside Of Inside By Forman

codebank의 이미지

보통 Network에서 값을 읽기전엔 select로 그 이벤트의 도착을 검사한 후에
또는 Timeout을 걸어놓고 read하는 경우가 대부분 아닌가 생각됩니다.
저도 일반적인(개인적인 용도의) 프로그램을 작성할 때는 아무 조건없이 작성하지만
일단 프로젝트가 발생되면 파일 디스크립션을 이용해서 select를 사용하는게 일반적인
방법이 아닌가 생각됩니다.
물론 select적용전에 timeout은 기본으로 설정을 하고요.
만일 select에서 이벤트를 받아들이고 read이전에 선이 단절된다면(최악의 경우...)
프로그램적으로 해결할 수 있는 방법이 있는지는 모르겠네요.
(그런 테스트를 해보려고 했지만 일단 select가 들어가면 그 타이밍을 찾는게 더
힘들어지더군요. 결국은 그 상황은 포기... :oops: )
결국 막아놓을것까지 다 막았다면 다음은 하늘의 뜻에 맡기는 수밖에 없지 않을까요?

이부분을 해결하신분이 답글을 달아주셨으면 좋겠네요.

------------------------------
좋은 하루 되세요.

송동섭의 이미지

select까지 확인된 데이터는 순간시점에 문제가 발생하여도 read를 통해 버퍼로 부터 읽혀지지 않나요? 그리고 통신에서 선의 단절이나 상대방 프로세서의 죽음등에 대한 특별한 방법은 없겠죠 ( 이상황에서는 상대측에서 데이터 전송이 불가능 하므로 ) 다만, 무조건적으로 이상확인 이후 disconnect와 reconnect만 보장이 된다면 다른건 신경을 써주지 않아도 된다고 생각이 드네요.

** Inside Of Inside By Forman

김경태의 이미지

select를 하고 나서 recv에 들어가는 것이 일반적인 routine이겠죠.

그런데 select 하고 나서 recv로 들어가도 가령 size가 잘못되는 경우는
my_rean과 같은 소스에서는 무한루프나 혹은 read holding과 같은 현
상이 생길 것 같습니다.

이 경우는 물론 recv이전에 걸어주는 select에서의 타임 아웃과는 다른
개념의 time out 매커니즘이 있어야 할 것 같습니다.

일반적인 방법으로는

1. alarm을 사용하고 EINTR을 이용하여 처리하는 경우
2. setsockopt를 이용하여 모든 recv에 timeout을 줄 수 있는 경우

가 있을 수 있을 것 같습니다.

1의 경우에는 물론 recv holding을 막을 수는 있겠지만 library에서는 온갖
경우에 다 적용되어야 하기 때문에 signal처리가 만만치 않을 것이고,

또한 1의 경우는 단지 window는 사용이 불가능하므로 window, unix계열
을 동시에 사용하는 library code에서는 적절치 않은 방법일 것입니다.

2의 경우는 과연 모든 경우의 recv holding을 막을 수 있을지 없을지 잘 모
르겠습니다.(어떤 경우는 처리가 않 될 수도 있을 것 같습니다.)

2의 경우의 또다른 문제는 반드시 recv할때마다 일정한 timeout을 적용해
야 한다는 난점때문에 일반적으로 적용하기에는 무리가 있을 것 같습니다.
(가령 엄청나게 큰 데이타를 받는다 거나 recv에서 무작정 기다려야만 하
는 로직에서는 적용이 어려울 것 같습니다.)

제 생각은 이런데 select 이후에 recv holding에 대한 다른 고수분들의 생각은
어떠신지요?

위분께서 <네트워크를 제거했을때의 log>가 뭐냐고 물으시는데 정확한 의미는
<Network를 제거한 상태에서의 client에 send하는 data>
이라고 보시면 되겠습니다.

아 그리고 위 루틴은 select 이후에 read하는게 아니고 그냥 <무작정 read>입
니다.

위 루틴을 쓰는 프로그램은 server에서 send해 주는 데이타를 무작정 기다려
야 하기 때문입니다.

moonzoo의 이미지

확실히 read에서 블럭중인지 부터 다시 한번 확인할 필요가

있을것 같습니다..

상대 호스트가 죽었을 때 read에서 당연히 감지한다고 생각하기에..

저도 경험상...잘 알려진 시스템 콜등을 사용하면서도..

예기치 못한 버그등에 부딪쳤을 경우에..

혹시 이 시스템 콜, 이 라이브러리에 문제가 있는건 아닌가

하고 의심도 많이 했습니다만..대개의 경우는..

전혀 다른 쪽에서의 자그마한 실수나 생각치 못했던 부분에서

문제를 야기시켰던 적도 많았기에 드리는 말씀입니다.

송동섭의 이미지

제 경험한 경우는 다음과 같습니다.
1. server process killed ( 예기치 못한 상황, kill 명령 (? 확인필요 ))
2. server process가 쥐고 있던 socket port close 못함 ( 하위 레이어에서 감지 못한듯 )
3. client select, read로 에러 감지 불가능
4. server로 write시도 (2회 이후 ) BROKEN PIPE 시그널 발생 ( write를 통해 상대 프로세서가 죽었음을 확인 )

여기서 중요한 포인트는 2번 일듯 싶네요. 우선 netstat루 server process 중단 이후 포트 상태를 확인해볼 필요가 있습니다.

** Inside Of Inside By Forman

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.