작성
·
326
1
안녕하세요.
데드락 탐지에 관해 질문드립니다.
1. PushLock()에서 lock_id를 LLockStack의 마지막 아이디하고만 비교하는 이유가 궁금합니다.
2. PopLock()을 할 때 _nameToId, _idToName, _lockHistory에서도 해당 락을 제거해줘야 하지 않나요? CheckCycle()에서 nameToId.size()로 걸린 락의 개수를 구하는 부분도 그렇고 히스토리를 통해 사이클을 검사하는데, 언락이 된 락은 더 이상 관리 대상이 아니라고 생각했습니다.
감사합니다.
답변 1
1
데드락 탐지에서 핵심은 락을 거는 모든 경로를 추적해서
락 거는 순서에 싸이클이 발생하는지를 보는 것인데요.
1.
A->A를 중첩해서 거는 것은 데드락이 발생하지 않기 때문에 무시하는겁니다.
2.
모든 경로에 대한 히스토리를 기반으로 판별하는 것이기에,
과거의 히스토리도 그대로 남기고 있는 것입니다.
Unlock했다고 history에서 삭제하면, 현재 잡혀있는 락 순서만 추적할 수 있는데
그러면 결국 확률적으로 일어나는 타이밍 이슈는 잡지 못하게 됩니다.
A, B라는 락이 있는데, A->B 순서로 잡을 수도 있고,
B->A 순서로도 잡을 수 있는 상황이 있다면 그 자체로 문제입니다.
그런데 이게 멀티쓰레드 환경에서는 극악의 확률로 일어나서
특정 쓰레드가 A->B로 잡은 다음에 바로 풀자마자 (B Unlock -> A Unlock),
다른 쓰레드에서 B->A를 간발의 차이로 나중에 Lock 해버린다면
당장 크래시가 안 나고 넘어갈 수 있겠죠.
이런 식으로 잠재적인 버그가 운좋게 지나가서
2주에 한 번 크래시가 나는 문제가 나는게 더 짜증나는 상황입니다. (QA에도 걸리지 않기 때문)
따라서 데드락 디텍터의 목적은 아예 데드락에 빠질 수 있는 후보군들을 싹 잡아주는 것이기 때문에
당장 데드락이 발생하지 않았다 하더라도 바로 잡아줘야 하는 것입니다.
와! 이해 됐습니다. 히스토리를 남겨두는 이유가 그거였군요!
A->B로 잡았다면 B->A로 못 잡게 한다!
락을 거는 것도 신중해지겠네요.
감사합니다.
P.S
만약 B->A 순서로 걸어줘야 하는 상황이 발생한다면
그건 프로그램의 구조 문제로 봐도 되는 걸까요?
만약 동시에 잡고 있진 않지만 어느 시점에 B->A 순서로
락을 걸어야 하는 상황이 생긴다면, 실무에서 관련한 경험이 있으셨는지,
있으셨다면 혹시 대략 어떤 식으로 해결하셨는지 조금이라도 알려줄 수 있으신가요!
감사합니다.
네 결과적으로 프로그램 설계 문제이긴 하지만,
큰 프로젝트에서는 몇십명이서 공동 작업을 하고 퇴사하고 입사하고 왔다 갔다 하기 때문에
그 방대한 100만줄 코드를 일일히 다 알 수가 없습니다.
A->B와 B->A가 둘다 등장하는 경우
대부분의 경우에는 적당히 코드를 수정해서 우회할 수 있는 경우가 많은데
이는 너무 코드에 따라 다르니 정확히 뭘 해야 한다고 말씀드리긴 힘듭니다.
2번 설명이 잘 와닿지 않습니다ㅠ데드락이 문제인 이유는 현재 잡고 있는 락끼리 교착 상태에 빠지기 때문인데, 히스토리에 남긴 과거 정보를 통해 '타이밍 이슈'를 어떻게 잡을 수 있는 것인지요..'타이밍 이슈'라는 것도 아직 잘 이해되지 않네요..