제품 여행

CUBRID contribute의 두번째 걸음, CUBRID 디버깅 하기

by 박세훈 posted Aug 09, 2018
디버깅은 실행중인 프로세스를 컨트롤할 수 있어 문제점을 찾거나 현재 로직을 확인 할 때 유용한 방법입니다.
이번에는 GDB를 활용하여 CUBRID server 프로세스를 디버깅해보도록 하겠습니다.

GDB 사용에 앞서 CUBRID 빌드가 되어 있어야 합니다.
CUBRID  빌드 관련 내용은 아래 링크를 확인하세요.
 
디버깅을 위해서는 'debug' 모드로 빌드해주세요. 
1
2
[root]vi build.sh
build_mode="debug"
cs
 
빌드시 에러가 발생한다면 표준에러만 파일로 리다이렉션하여 확인하는 것이 좋습니다. 
1
2
[root]vi build.sh 2> error.out
vi error.out
cs

빌드가 완료가 되었다면 bash_profile 파일에 PATH 관련 정보를 추가 저장합니다. CUBRID 위치는 build시 저장한 위치로 변경하세요. 
1
2
3
4
5
6
7
8
9
10
cd ~
[root]vi .bash_profile
export CUBRID=/cubrid10.1/CUBRID
 
export CUBRID_DATABASES=$CUBRID/databases
export PATH=$PATH:$CUBRID/bin
export LD_LIBRARY_PATH=$CUBRID/lib:$LD_LIBRARAY_PATH
CLASSPATH=$CUBRID/jdbc/cubrid_jdbc.jar
export CLASSPATH
[root]source .bash_profile
cs

demo DB를 생성합니다.
1
2
3
4
5
6
cd $CUBRID
mkdir databases
cd databases
mkdir demodb
cd demodb
../../demo/make_cubrid_demo.sh
cs

CUBRID service를 구동합니다.
1
2
cubrid service start
cubrid server start demodb
cs

이제 디버깅 할 준비가 끝났습니다.
이번에는 cub_server 프로세스의 'log_flush_thread' 쓰레드에서 'group_commit' 파라메터가 어떻게 구현되어 있는지 확인해 보겠습니다.
'log_flush_thread'는 active log를 log volume에 flush하는 쓰레드로 주기적으로 혹은 요청을 받아 처리하게 되어있습니다. 

cub_server 프로세스를 GDB로 디버깅을 시작합니다. 
1
2
[root] ps -ef | grep cub_server
[root] gdb –tui cub_server 67310
cs
 
cub_server 프로세스는 gdb에 의해 멈춰 있는 상황입니다.
Thread를 확인해 봅니다. 
1
(gdb)  thread apply all bt
cs

pastedImage (2).png

'thread apply all bt' 명령어를 사용하면 상당히 많은 thread를 확인 할 수 있는데 그중 2번 thread가 'thread_log_flush_thread' 임을 확인 할 수 있습니다.


'thread 2' 로 해당 thread로 들어 갑니다.
1
(gdb)  thread 2
cs

GDB에는 'step', 'next', 'break' , 'continue' 등의 명령이 있습니다. 여기서는 이 네가지 명령에 대해서 설명하겠습니다.
step   : 한줄씩 실행함. function으로 들어감.
next  :  한줄씩 실행함. function으로 들어가지 않음.
break : 특정 위치에서 멈춤.
continue : break 이전까지 실행함.

특정함수를 Break 하고 continue 하도록 하겠습니다.
1
2
(gdb) b logpb_flush_pages_direct
(gdb) c
cs

logpb_flush_pages_direct 함수에  break를 걸고 continue를 하면 다시 break 지점으로 돌아온 것을 확인 할 수 있습니다.
'log_flush_thread' 가 루프를 통해 동일 로직이 반복되는 것이지요.

지정한 Break point 를 제거 하겠습니다.
1
2
(gdb) info b
(gdb) d 1
cs

'next'을 사용하여 디버깅을 계속해 봅니다.
1
2
(gdb) n
(gdb) n
cs
pastedImage.png

디버깅 중에 'GROUP_COMMIT_INTERVAL_MSECS' 파라메터와 관련있는 부분을 찾았습니다.

gc_interval 변수에 값을 넣고 있는데요. 해당 값을 확인해봅니다.
1
(gdb) p gc_interval
cs

해당 파라메터를 설정하지 않아 default 값인 '0' 나오네요.
파라메터를 설정하고 디버깅하면 해당 값이 있을 때 어떻게 동작하는 지 확인 할 수 있겠습니다.
그전에 소스코드를 TEXT 에디터로 확인해 보는 것도 좋겠죠.

backtrace 명령어를 사용하여 현재 소스 코드 위치를 확인합니다.
pastedImage (1).png


/src/thread/thread.c 파일에 3737줄을 찾으면 해당 코드가 있겠네요.
'gc_interval' 변수에 집중하여 어떻게 구현되어 있는지 확인하면 더 효과적이겠습니다.
이후에는 직접 진행하면서 분석해보시기 바랍니다.

디버깅 위주의 내용을 적다보니 제가 분석하는 순서와는 조금 다른 점이 있는데요.
위에 내용이라면 먼저 'GROUP_COMMIT_INTERVAL_MSECS' 파라메터를 TEXT EDITOR등을 활용해서 전체 소스 검색을 하겠습니다.
그리고 'log_flush_thread'에 해당 내용이 있는 것을 찾고, 확인 후 디버깅을 시작하겠습니다. 

지금까지 간단하게 알아본 cub_server 디버깅 방법이었습니다.