본문 바로가기

하루하루/개발

Multi-Logic-Threaded GameServer 3부


2부에서 싱글톤 문제가 그렇게 해결 되는 듯 했다.

그런데 봇 테스트 중 가끔 일부 쓰레드가 정지되는 경우가 발생했다.

디버깅을 해보니 'DeadLock'이었다.

그리고 그 'DeadLock'의 원인은 바로 2부에서 작성했던 Singleton Locker때문이었다.

싱글톤 사용 시 Lock을 걸다보니 A싱글톤 내부에서 B싱글톤을 호출하고, B싱글톤 내부에서 A싱글톤을 호출하는 경우에 DeadLock이 발생했다.

언제나 그렇듯 이 사실은 안 순간 정말 절망이었다..

그렇다면 모든 싱글톤 소스에서 타 싱글톤 호출하는 부분을 찾아서 수정해야 된단 말인가....ㅡㅡ;

처음 싱글톤 문제를 알았을 때 처럼...백지화할까라는 생각이 들었다.

그래도 어떻게든 해법을 찾고 싶었다. 그래서 제작하게 된 것인 DeaLock Checker이다.


'DeadLock'...

아마 멀티 쓰레드 프로그래밍을 사용하다보면 필연적으로 마주치게 되는 버그 중 하나다.

골치 아픈 버그들이 그렇듯 DeadLock이 발생하면 당황할 수 밖에 없는 이유는 '재현이 잘 안되는 버그'이기 때문이다.

정말 작은 한 순간 타이밍의 틈을 비집고 들어와서 시원하게 꽝~~하고 터져 버린다.

DeadLock의 특징은 항상 터질 '가능성'을 가지고 있다가 아주 작은 타이밍적인 우연의 일치가 맞았을 때 터진다는 점이다.

내가 주목했던 점은 바로 그 '가능성'이다.

만약 아직 터지지는 않았지만 현재 코드가 가능성을 가지고 있다면, 그 '가능성'이라는 측면을 미리 확인 할 수 있는 방법이있을 꺼라고 생각했다.

예를 들어 '가'쓰레드와 '나'스레드가 있다.

그 중 '가' 쓰레드가 'A' CS를 호출하고, '나'쓰레드가 'B' CS를 호출한다.

아주 가끔 '가'쓰레드가 'A' CS를 호출 후 'B' CS를 호출하는 경우고 있고, '나'쓰레드의 경우 그 반대의 경우가 가~끔 있다.

아마 몇 번의 테스트에서는 괜찮겠지만, 아주 가끔 DeadLock이 발생할 여지가 있다.

그렇다면 각 쓰레드별 CS 호출 기록을 남기면 어떨까?

예를 들어 라이브 서비스 하기 전에 로봇 테스트나 사내 테스트를 진행 할 때 세팅을 하면 각 쓰레드별 CS호출 기록을 남기는 것이다.

그리고 서버 종료 시점이나 매우 긴 틱에 각각의 쓰레드간에 서로 크로스 하는 경우가 없는 지 검사하는 것이다.

다소 무식하고, 성능은 떨어지겠지만 DeadLock의 가능성을 미리 알 수 있다.

이 아이디어를 처음 생각했을 때 좀 무식하기는 하지만, 라이브 서비스에서는 해당 기능을 꺼버리면 되니

성능 문제는 없으므로 알고리즘만 잘 짜여지면 나름 괜찮은 방법이라고 생각했다.

하지만 한편으로는 과연 이렇게까지 해야지만 DeadLock이 검출될 정도로 복잡도가 높고, 쓰레드간 모듈화가 제대로

되지 않았다면, 그 것 자체가 문제이지는 않을까 라는 생각도 들었다....

다행이 지금 프로젝트는 그 정도까지는 아니었지만, 나중에 이거 믿고 너무 멀티 쓰레드를 남발하는 경우는 조심해야 될 것 같다.

그리고 아직 문제가 남았으니....
 
그렇다면 각 쓰레드별 CS호출 기록을 어떻게 모두 남길 것이며..어떻게 검사 할 것인가~라는 문제가 남았다.

이 부분은 회사 소스코드를 사용할 수 없으니 테스트 프로젝트로 남겨야 될 것 같다.

'하루하루 > 개발' 카테고리의 다른 글

Multi-Logic-Threaded GameServer 2부  (0) 2010.04.12
Multi-Logic-Threaded GameServer 1부  (0) 2010.04.09
LFH (Low Fragmentation Heap)  (0) 2009.04.12
Mock 객체 활용법  (1) 2008.04.29