socket 공유시의 경쟁에 관한 질문...

nTachyon의 이미지

제목에서 처럼 소켓을 여러 프로세스 또는 스레드 간에 공유하는 부분에 대해 궁금증이 있어 글을 몇자 남깁니다.

부연 설명을 해 주시면 감사하겠습니다.

일단 상황을 말씀드리자면...

1. listen 소켓을 global 변수로 둔다.
2. 여러 스레드에서 이 listen 소켓을 이용해 accept 대기를 한다.
※ listen 소켓은 SO_REUSEADDR 옵션을 주었습니다.

위와 같은 상황에서 처음에는 뮤텍스를 하나 두고서
- 이 뮤텍스를 얻기 위한 경쟁에서 승리(?!)하는 스레드가 뮤텍스 locking 후
- accept 대기를 하고...
- accept가 수행 된 후엔 뮤텍스를 unlock
하는 구조로 작성하였습니다.

pthread_mutex_lock(&lock_4_listen);
sock_conn = _accept(listen_sock, (struct sockaddr*) &sa, &sa_len);
pthread_mutex_unlock(&lock_4_listen);

근데 플랫폼이 linux이다보니 pthread_mutex_unlock에서 자꾸 segmentation fault 나는 관계로,
어찌어찌하다 우연히 뮤텍스 lock/unlock 코드를 주석으로 막고 돌렸는데도 잘 돌아가네요.

이 부분에서 제가 궁금한 것이...

지금처럼 뮤텍스 lock/unlock 없이 모든 스레드가 동시에 하나의 listen 소켓에 대기를 하여도 SO_REUSEADDR 옵션만 주어진다면 충돌 없이 운영체제 차원에서 accept를 수행할 순서를 정해주는 것인가요?

만일 그렇다면 뮤텍스를 쓸 필요가 전혀 없다는 생각이...

눈에 보이는 결과는 그런 것 같지만, 이 부분에 대해서 좀 더 명확한 설명을 듣고자 합니다.

많은 조언 부탁드립니다.

비가 오네요... 좋은 소식을 가져다 주는 봄비였으면 합니다.

alsong의 이미지

확실히 unlock에서 죽는지 확인하시고요. gdb로 체크
lock_4_listen의 값에 영향을 미칠만한 부분을 찾아보세요.
전역변수라면... 전후의 선언된 다른 전역변수가 힙크기에 맞게 사용되고 있는지
printf문에 인자를 잘못 사용했다던지.....

표준함수가 오류를 낼경우는 대부분이 사용자 프로그래밍 잘못입니다.
오류가 난 원인을 알아내지 못한채 피해가면 후일 반드시 보복이 날아 옵니다. ^^;

Quote:
근데 플랫폼이 linux이다보니 pthread_mutex_unlock에서 자꾸 segmentation fault 나는 관계로

리눅스가 그렇게 만만한 OS를 아닙니다. 리눅스를 믿으세요 ^^;

그나저나 백수 언제 탈출하냐... ㅡㅡ; 배고파라.

saeparan의 이미지

제 생각에도, alsong 님의 의견과 같이 전역변수 lock_4_listen 의 근처에 있는 array 나 포인터 변수등이 값을 넘어가면서 mutex 변수가 뭉개져 버리는게 아닐까 하는 추측이네요.

처음에는 프로그램이 잘 돌다가 어떤 순간에 SIGSEGV 가 발생된다면 그럴 확률이 높겠지요.

pthread_t 를 신뢰하고 아주 애용하고 있는 사람으로, 그런 문제가 linux 에서 발생된다면, 이미 전 어마어마한 재앙 수준의 일이 벌어졌을겁니다.

그럼.

nTachyon의 이미지

Quote:
확실히 unlock에서 죽는지 확인하시고요

확실히 unlock에서 죽는답니다... 뱉어낸 core dump에서 그리 말해주고 있으니 ㅜㅡ

Quote:
lock_4_listen의 값에 영향을 미칠만한 부분...

lock_4_listen은 제가 위에서 적은 부분 말고는 사용되는 곳이 없답니다.
destroy 하는 곳 말고는...

제 개인적인 생각입니다만,
unistd.h 헤더를 보면... _POSIX_THREAD_PROCESS_SHARED 가 정의된 부분이 주석으로 막혀있고... (2.6버전에는 NPTL이 들어가면서 이 기능이 된다고는 합니다만...)
리눅스에선 스레드 = 프로세스로 알고있는지라 혹여 global로 된 lock_4_listen 이 공유되다가 문제를 일으키는 것이 아닐까 하는 막연한 (이런게 안좋다는 건 알지만, 원인을 몇일째 찾지 못한 마당에 이러한 추측이라도 -_-;;; ) 생각도 해 봅니다.

특히나 이렇게 segmentation fault가 매번 생기는 것이 아니라 잘 돌아가다 갑자기 생기는 관계로 님들 말씀처럼 다른 곳에 문제가 있을지도 몰겠다... 는 생각을 하는 상황에선 별 생각을 다 해봅니다.

참 그리고... 지금처럼 뮤텍스 lock/unlock 없이 모든 스레드가 동시에 하나의 listen 소켓에 대기를 하여도 SO_REUSEADDR 옵션만 주어진다면 충돌 없이 운영체제 차원에서 accept를 수행할 순서를 정해주는 것인가요?

라는 질문에 대한 조언도 궁금합니다.

만약 OS 차원에서 이 스케쥴링이 된다면 굳이 mutex를 쓰지 않아도 되겠기에.

테스트는 계속 돌려봐도 아직은 별 문제는 없습니다만, 답변을 기다리며 더 테스트를 해 보겠습니다.

오늘 날씨가 쌀쌀하네요... 좋은 하루 되세요

bugiii의 이미지

accept 하고 SO_REUSEADDR 옵션하고 상관없는 걸로 알고 있습니다.

그 옵션은 새로운 리슨 소켓을 해당 포트에 바인딩할 때 의미 있는 것 아닌가요?

bugiii의 이미지

아 또하나 있는데, accept 주변을 동기화 객체로 막는 것이 속도 때문만이 아니라 같은 fd를 accept하지 못하는 OS 때문이기도 하다고 stevens 아저씨 책에는 나와 있군요...

alsong의 이미지

혹시나 -D_REENTRANT(없으면) 한번 추가 해보세요.

accept가 thread safe한 unix가 있다고는 들었습니다만
리눅스가 thread safe한지는 잘 모르겠습니다.

별도움이 안되었군요... ㅡㅡ;

그나저나 백수 언제 탈출하냐... ㅡㅡ; 배고파라.

nTachyon의 이미지

(gdb) where
#0  0x4002d260 in __pthread_alt_unlock () from /lib/i686/libpthread.so.0
#1  0x4002a13c in pthread_mutex_unlock () from /lib/i686/libpthread.so.0
#2  0x08049b2a in thread_func (arg=0x40852a3c) at thread_pool.c:221
#3  0x40029941 in pthread_start_thread () from /lib/i686/libpthread.so.0

테스트 중인 플랫폼은 리눅스입니다.
Linux my_server 2.4.18-14smp #1 SMP Wed Sep 4 12:34:47 EDT 2002 i686 i686 i386 GNU/Linux

-D_REENTRANT 심볼을 정의하고 컴파일 했을때 나온 에러이니...

앞서 올라온 다른 글들을 보면... pthread_mutex_unlock에서 SIGSEGV 난다는 분들이 몇분 되시던데... 답글들을 보며 정리를 해봐도 이거다... 라는 명확한 답이 안보입니다.

리눅스에서 스레드는 프로세스니까... pthread의 뮤텍스 보단 세마포어를 써야하는건가 싶기도 하고...

일단 pthread_mutex_unlock이 리눅스에서 SIGSEGV 발생시키는 이유를 아시는 분 계신가요?

적고보니 횡설수설이군요. (--)(__)(--);;

nTachyon의 이미지

제목처럼 세마포어로 방향전환 했습니다.

많은 조언 주신 분들 감사드려요.

세마포어로 돌리니 문제없이 잘 돌아가네요.

리눅스에서 뮤텍스는... 이라는 의문점을 가지고 가네요... 계속 찾아봐야죠^^

댓글 달기

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