윈도우 프로그래밍

SetEvent(..) & 멀티쓰레드 버그

하늘흐늘 2009. 4. 28. 02:56
반응형

꽤나 재미있는 버그였다...

int tst;

//Thread#1
...
WaitForSingleObject(...);
printf("%d", tst);
...

//Thread#2
...
tst=3;
SetEvent(...);
tst=4;
...

이 상황에서 Thread#1이 Thread#2를 기다리다가 tst값을 찍을 경우, 찍히는 값은 3일까? 4일까?
 이 코드는 전형적으로 시그널을 기다리는 코드로 Thread#1이 Thread#2의 시그널을 기다리고 있다. 그런데 중요한 것은 OS동작이다. 흔희 생각할수 있는, SetEvent(...) 호출한 후의 Context Switching은 바로 일어나지 않을 수도 있다. 이런경우 일정량 만큼 SetEvent(...) 이후의 코드가 실행되다가 Context Switching이 일어난다. 즉, tst의 값으로 찍히는 값은 3일 수도 있고 4일 수도 있고 이는 OS의 쓰레드 스케줄링과 관계가 있게 된다.  
 내가 오늘 몇시간 동안 헤멘 버그가 이것이었다. 디버깅하는데 그나마 운이 좋게도 2번 중 1번은 문제가 발생하고 1번은 정상 작동하였다. (말이 운이 좋아서 이지, 이런 류의 쓰레드 관련 버그들은 사람 미치게 만들지... --;) 

 그럼 이런 문제의 해답은 무엇일까? 정확한 답일지는 모르겠지만, 나는 그냥 생각지 못한 코드가 실행되는 것을 막기 위하여 SetEvent(...) 코드를 하나 더 추가하였다.

 

int tst;

//Thread#1
...
WaitForSingleObject(...);
printf("%d", tst);
SetEvent(...);
...

//Thread#2
...
tst=3;
SetEvent(...);
WaitForSingleObject(...);
tst=4;
...

왜? CriticalSection을 쓰지 않으시냐고? 뭐, 상황이 한 쓰레드가 진득하게 다른 쓰레드를 기다려야 하는 상황인지라.... Conditional Lock의 일종인 Event쪽이 좀 더 적합하다고 여겨졌기 때문이었다.

마지막으로 Vista에서 Visual Studio 2009로 디버깅 하다가 발견했는데 "Visual Studio가 강력하긴 강력하구나, 이런 쓰레드 관련 상황을 디버그 상황에서 실제와 유사하게 디버깅하게 해주니..." 라는 생각이 들었다. 전에 안 그랬던거 같은데, 그래서 쓰레드 관련 버그 잡기가 꽤나 골치 아팠던거 같은데.. 아닌가..?


반응형