주(primary) 스레드가 종료되면 나머지 스레드도 종료될까? :: 2007/07/04 14:15


질럿: 윈도우즈 App에서 주 메인 쓰레드가 종료되면,,,,동작 중에 생성했던 쓰레드들도 종료되나요?
신영진: 그렇지 않나요?
질럿: 나도 그런걸로 알고 있는데... 리눅스에서는 안그런것 같아서요
질럿: 앞에 앉은 사람이... 주메인 쓰레드가 종료해도... 다른 쓰레드들은 안 죽는데요
백지훈: 그러면 메인 쓰레드가 종료하면 자식 쓰레드가 남아서 일을 처리한다는 건가요?

시작은 이랬다. 질럿님의 당연한 듯한 질문. 돌이켜 보니 사실 내가 스레드에 대해서 알고 있는 사실은 하나도 없었다. ㅠㅠ 윈도우 개발자가 생각하는 스레드는 무엇일까? 몇 년간 윈도우 환경에서만 개발을 해 온 나에게는 다음과 같은  막연한 생각들이 있었다.

1. 스레드는 프로세스에 포함되는 구성 요소다.
2. 프로세스는 반드시 하나 이상의 스레드로 구성된다.
3. 커널은 스레드 단위로 작업을 스케줄링한다.

1번 때문에 스레드는 프로세스 보다는 가볍다는 장점이 있다. 가상 주소 공간을 필요하지 않기 때문이다. 또한 변수들이 공유된다는 특징도 생긴다. 그래서 동기화에 신경을 써야 한다. 2번은 프로세스는 실행 단위가 아님을 나타낸다. 프로세스는 단지 스레드를 수행시키기 위한 컨테이너 정도로 생각할 수 있다. 코드는 전적으로 스레드에 의해서 수행된다. 3번 때문에 컨텍스트 스위칭 비용이 발생한다. 이 때문에 다중 스레드가 싱글 스레드보다 효율이 느린 경우가 많다. 항상 스레드의 적절한 개수를 신경써야 한다.

이런 막연한 지식들을 바탕으로 질럿님의 질문으로 돌아가보자. 주(primary) 스레드가 종료되면 나머지 스레드도 종료될까? 여기에는 큰 함정이 숨어 있다. 바로 주(primary) 스레드라는 말이다. 통상적으로 윈도우 개발자들은 WinMain이나 main을 수행시킨 최초의 스레드를 주(primary) 스레드라고 말한다. 첫번째 스레드, first thread라 하지 않고 왜 주(primary) 스레드라고 말할까? 그건 나도 모른다. 하지만 그게 함정이다. 주(primary)라는 말은 뭔가 이 녀석이 순서 외에도 특권을 가지고 있다는 생각을 하게 만들기 때문이다. 그래서 보통 주(primary) 스레드가 죽으면 다른 것도 죽을 것이라고 생각한다.


위와 같은 테스트 코드를 테스트 해보자. 메인이 끝나니 다른 것도 끝나는 것처럼 보인다. 이제 우리의 막연한 생각을 뒷바침해줄 근거까지 생겼다. "이제 뭐 더 이상 토론할 필요도 없는 것이다."라고 생각한다면 정말 제대로 함정에 빠지는 것이다.

함정에 빠지지 않기 위해서는 역으로 질문을 던져야 한다. main이 리턴되면 왜 프로그램이 끝나는 것일까? 주(primary) 스레드가 종료되었기 때문에 끝나는 것일까? 의심을 품고 디버깅을 해보면 답이 보인다. 메인 리턴 후의 경로를 살펴 보면 최종적으로 CRT 코드에서 ExitProcess를 호출하는 것을 볼 수 있다. 그렇다. 주(primary) 스레드가 끝나서 프로그램이 끝난게 아니라, 주(primary) 스레드 끝에서 ExitProcess를 호출해서 프로그램이 끝난 것이다. 그렇다면 ExitProcess를 호출하지 않는다면?


위와 같이 코드를 고쳐 보았다. 저 코드는 진짜 질문의 의도대로 주(primary) 스레드만 종료 시킨다. 테스트 해보면 알겠지만 남은 두 스레드로 프로그램은 버젓이 돌아간다. 두 스레드가 모두 종료되면 프로그램도 종료된다.

프로세스에 포함된 스레드 간에는 주, 종관계가 없다. 다 평등한 관계다. 따라서 주(primary) 스레드란 말도 잘못된 것이다. 시작 스레드 내지는 첫번째 스레드 정도가 더 정확한 용어라 할 수 있다. 또한 프로세스는 기본적으로 모든 스레드가 종료되어야 끝이난다.

스폰서
글타래

  • 2주간 인기 글
  • 2주간 인기글이 없습니다.
Trackback Address :: http://jiniya.net/tt/trackback/526
  • Gravatar Image.
    오스카 | 2007/07/04 14:51 | PERMALINK | EDIT/DEL | REPLY

    예전에 똑같은 문제로 한 번 테스트를 해보고 솔직히 좀 놀랐었어요.
    당연히 주종 관계가 성립될거라고 생각했는데. ^^
    글 잘 봤습니다~

    • Gravatar Image.
      codewiz | 2007/07/04 23:20 | PERMALINK | EDIT/DEL

      저도 그렇고 많은 개발자가 막연하게 그렇게 생각하는것 같아요. ㅎㅎ

  • Gravatar Image.
    object | 2007/07/04 22:50 | PERMALINK | EDIT/DEL | REPLY

    으아~ 제가 겪은 것과 똑같은 삽질을 하셨네요 :) 지난 번 pthread와 유사한 라이브러리를 만드는 숙제를 할 때 제가 가졌던 의문이었죠. 저도 윈도우에서만 코딩하다보니 primary thread (main thread보다는 primary라고 하지 않나요?)가 끝나면 모두 끝나는 줄 알았는데 말씀처럼 ExitThread를 해버리면 딱 primary thread만 종료가 되죠. 참 신선한(?) 경험이었습니다.

    • Gravatar Image.
      codewiz | 2007/07/04 23:22 | PERMALINK | EDIT/DEL

      제가 영어를 잘 못해서 그렇습니다. ㅎㅎ primary thread라고 하는게 맞을것 같네요. ^^

      아. 그리고 질문하신 질럿님도 pthread 관련 코드를 보다가 의문을 품게 된 것이었어요. ㅎㅎ pthread_exit위에 주석으로 메인이 끝나도 다른 스레드가 일을 처리한다고 되어 있었다고 하더라고요.

  • Gravatar Image.
    object | 2007/07/04 22:56 | PERMALINK | EDIT/DEL | REPLY

    참 여담으로 제가 생각하는 윈도우에서의 스레드 정의는... register와 call stack (컨텍스트)을 가지면서 CPU 자원을 사용할 수 있는 최소의 실행 단위라고 생각합니다..

  • Gravatar Image.
    drvoss | 2007/07/05 09:48 | PERMALINK | EDIT/DEL | REPLY

    익셉션 처리시에 요 문제를 겪은적이 있습니다. SetUnhandledExceptionFilter로 커스텀하게 익셉션 보고 처리를 해주었는데, 쓰레드에 인자로 포인터를 넘겨주어 main에 있는 변수를 참조해서 쓰레드를 돌리게 할때 main 함수에서 익셉션이 나버리면 main 함수안의 변수를 참조하는 쓰레드에서 원하지 않는 값을 참조하므로, 거기서 또 익셉션이 나고, 익셉션을 잡은 오류 보고 창이 그냥 죽어 버리는 현상이였습니다.

    • Gravatar Image.
      codewiz | 2007/07/05 13:13 | PERMALINK | EDIT/DEL

      그런 일이 있었군요.
      어떻게 해결 하셨는지도 궁금하네요.
      main 변수를 참조하지 않게 하셨나요?

  • Gravatar Image.
    drvoss | 2007/07/05 09:59 | PERMALINK | EDIT/DEL | REPLY

    아 그리고, 마우스 하나 보냈습니다. 디자인을 우선으로 선택했어요 ^^

  • Gravatar Image.
    zoops | 2007/07/05 10:45 | PERMALINK | EDIT/DEL | REPLY

    와~
    명확하네요~ 그렇군요... 역쉬 영진씨 짱~

    • Gravatar Image.
      codewiz | 2007/07/05 13:14 | PERMALINK | EDIT/DEL

      지훈님도 짱이예요. ^^
      그 때 대화 내용 참 재밌었어요.
      많은 것을 배울 수 있었고요.

  • Gravatar Image.
    drvoss | 2007/07/05 10:59 | PERMALINK | EDIT/DEL | REPLY

    노트북 마우스가 아니였습니다.!! 오후에 다시 골라 보내드릴께요~~ ^^

    • Gravatar Image.
      codewiz | 2007/07/05 13:13 | PERMALINK | EDIT/DEL

      감사합니당. ㅎㅎ
      잘쓸께용.
      제가 괜히 귀찮게 한 건 아닌가 하는 흐흐~~~

  • Gravatar Image.
    snaiper | 2007/07/05 11:36 | PERMALINK | EDIT/DEL | REPLY

    쓰레드는 원래 주종관계..이런거 없지. 만약 그렇다면 쓰레드 스켸쥴링할 때 다 똑같아야만 한다는 전제를 벗어나는게 아닐까? 이상한 소린가 ㅎㅎㅎ 꽤 오래전에 왜 프로그램은 죽었는데, 프로세스는 살아 있을까를 보고 디버깅 해본 적이 몇 번 있는데, 결국 Primary Thread 만 죽었다는 거였지. 니가 적은데로 그렇게 알고 있는 사람들이 많은지 이런 문제를 안고 있는 프로그램 꽤 많더라구...^^ 역시 GOOD!

    그나저나 Primary는 한글로 해석이 잘못 된게 아닐까 싶네..."초기의" 라는 뜻이 맞지 싶은데...HDD에서 Primary, Slave의 영향 때문인지 그렇게 해석된게 아닐까 하는 추측을 해본다는 ^^:::

    • Gravatar Image.
      codewiz | 2007/07/05 13:16 | PERMALINK | EDIT/DEL

      알고 나니 당연한건데 ㅎㅎ 모를때는 또 안그렇더라고요. ^^ primary는 hdd의 영향을 받은 건 맞구요. ㅎㅎ 주요한이란 뜻도 있다길래 그렇게 해석했어요 ㅋㅋ 초기의 라고 해석해 버리면 글이 이상하게 돼 버려서 ㅋㅋ

  • Gravatar Image.
    drvoss | 2007/07/05 22:06 | PERMALINK | EDIT/DEL | REPLY

    처음에는 익셉션이 나는 그 순간 프로세스가 소유 하고 있는 모든 쓰레들 모두 강제 종료 시키고 편한 상태에서 오류 수집을 하려 했습니다. 그러다 이게 아니다 싶어서, Modern C++ Design 에 나오는 피닉스 기법을 써보려 했습니다. 익셉션이 난 상태에서는 이미 만신창이가 된 상태인데 이도 저도 너무 복잡해 지는겁니다. 가능할 지도 모르겠고..

    그래서 두가지 방법을 썼는데, 첫번째는 걍 죽게 냅뒀습니다. 요즘 OS가 너무나 정리를 잘해줘서 나름 보기 나쁘지 않았습니다. 두번째는 익셉션 난 순간에 콜스택과 로드된 환경정보, 익셉션정보등을 파일로 저장해서 디스크에 저장해 두고, 다음 실행시 해당 덤프 파일이 있으면 서버로 전송하게 했습니다.

    snaiper님을 답글을 보니, 복잡하더라도 쓰레드를 정리해 주는게 좋을것 같네요.

    쓰다보니, 좋은 팁이나 방법을 기대하셨다면 실망이 크시겠네요 ;)

    • Gravatar Image.
      codewiz | 2007/07/06 15:18 | PERMALINK | EDIT/DEL

      Modern C++ Design에 나오는 피닉스 기법은 어떤 방식이죠? 제가 책을 읽었는데 얄팍하게 읽어서 그런지 잘 기억이 나질 않네요. ㅋㅋ 책을 찾아보려고 해도 부산 집에 있어서 ㅠㅠ

      전 Unhandled Exception handler는 간단한게 좋다고 생각합니다. 덤프 정보를 저장하고 추후 서버로 전송하는 정도면 충분하지 않나요? 물로 사용자의 상태까지 저장해서 복구시켜 준다면 더 좋을 것 같네요 ^^

  • Gravatar Image.
    drvoss | 2007/07/08 19:26 | PERMALINK | EDIT/DEL | REPLY

    고내용이 워낙 책을 대충봐서 생각이 가물가물한데, 아마 인스턴스가 삭제된 공간에 남아 있는 데이터를 그대로 이끌어서 다시 객체를 생성하는걸로 본것 같습니다. 무슨 함수 하나가 중요한거였는데 aexit() 인가 할껍니다. 책이 저도 집에 있는데, 저 가출해서 집에 안들어갑니다. (자취 시작했어요~ T_Tb)

    네.. 말씀하신 그 방법이 최상인것 같습니다. 그런데 사용자의 정보를 얻어 오려면 꼭 동의를 얻어야 나중에 문제가 없습니다. 그래서 정보를 보낸다는 다이얼로그를 보여주는 시점도 중요하고, 동의를 얻을때도, 최대한 간절하고 부드럽고 애처롭게 보여지면서 잘못을 잘 전달해주는 방법이 중요합니다.

    • Gravatar Image.
      codewiz | 2007/07/08 23:38 | PERMALINK | EDIT/DEL

      피닉스라 불릴만한 테크닉이네요. ㅋㅋ
      자취는 어디서 하세요? 서울대 입구?

  • Gravatar Image.
    drvoss | 2007/07/10 13:37 | PERMALINK | EDIT/DEL | REPLY

    네. 모텔 옆이라 좀 안좋기도 하고 좋기도 하고 그래요. ^^ 그리고, 마우스 보내드렸어요. 15일 정도 까지 기다려 보시다가 안오면 저에게 연락 주세요^^

    • Gravatar Image.
      codewiz | 2007/07/11 12:38 | PERMALINK | EDIT/DEL

      저도 예전에 거기서 자취한 적 있어요 *^^*
      패스트푸드점이 많다는게 장점아닌 장점이었다는 ㅎㅎ

  • Gravatar Image.
    minchul | 2016/10/13 16:58 | PERMALINK | EDIT/DEL | REPLY

    2016년에 해당 글에서 참 지식(!!)을 깨닫고 갑니다.
    감사합니다.

Name
Password
Homepage
Secret