-
반응형
항상 alpha, beta로 개발된 기능은 그 자체로 simple하게 정상 동작하지만, release가 되면 문제가 손쉽게 발생하는 것 같다. 또한 이렇게 발생한 문제점은 특정 조건이라는 전제가 붙기 때문에 원인 분석에 어려움을 겪기 마련이다. 특히 재현이 잘 안되기 때문이다. 그런 의미에서 오늘은 원인을 찾기 위해 힘든 하루를 보냈다.
데이터가 일부 누락되는 상황이 간헐적으로 발생하는 현상이었데, 무엇이 문제였을까.
문제는 linked list 사용방법의 차이점에서부터 시작했다.
list_head, list_for_each_safekernel에서 linked list 사용할 때와 list_for 시리즈를 사용할 때랑 조금 차이가 있다.
struct list_head{ struct list_head *next, *prev; };
kernel에서 제공되는 linked list API는 next를 사용해야 첫번째 데이터(element)를 만날 수 있다.
하지만 list_for_each_safe에서는 데이터 접근을 위하여 next를 사용하면 안된다. 그 이유는 아래와 같이 next에 접근해서 사용하도록 define 되어 있기 때문이다.
#define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next)
버그가 있는 코드에서는 list_for_each_safe(pos, n, head)가 아닌 list_for_each_safe(pos,n, head->next)의 형태로 사용하고 있다. 결국 두번째 데이터부터 list 전체를 뒤지는 로직이 되어버린 것이다.
next or prev는 직접 사용하게 하고, list_for_each_safe에서는 next를 직접 사용하지 않게 되어 있으니 개발자 실수가 생길 가능성이 있다.
물론 코드를 작성하는 개발자가 신경써야 할 부분이지만 아래 처럼 next와 prev에 대해서도 define이 제공됬으면 일관성있게 사용할 수 있어서 실수를 줄일 수 있었을 것이다.
문제를 수정하긴 했지만 고생한걸 생각하니 이런 부분들은 많이 아쉬웠다.
#define list_next(head) (head)->next#define list_prev(head) (head)->prevSee also- linux kernel에 구현되어 있는 linked list의 설명은 여기가 가장 잘 되어 있는 것 같다.
반응형