This is a demonstration of debugging procedure using GDB (GNU Debugger)
Contents |
$> cd /repos/drizzle/mybranch/ $> ./config/autorun.sh && ./configure --with-debug && make -j2
(Note: Building without the --with-debug and -j2 options may produce strange results with line numbers in source files) Now you have the choice to start the server for debugging with or without standard testing suite.
better to fist test the build by executing the standard test suite. like:
$>make test
Go to the tests directory and start Drizzle in GDB. (dtr is a perl script part of test suite. it wrapps GDB also).
$> cd tests $> ./dtr --start-and-exit --gdb
This will pop open a GDB instance for the server process, and it will be waiting for client connections. (remember that drizzle's default port is 4427. but dtr uses 9306
alternatively you can use gdb without dtr (the testing suit)
$cd drizzled/ $gdb drizzled
now you will be inside GDB where you can set arguments and run the code.
(gdb) set args --console-enable --drizzle-protocol-port=9306 --datadir=/home/jpipes/repos/drizzle/working/drizzled/ (gdb) run
Important Note: --console-enable simplfies debugging procedure by providing a server console.
so no need to have a separate client connection and you can execute commands on server console itself.
You can create one client session like:
$> ../client/drizzle --user=root --port=9306
You will notice that the client seems to just "hang". Switch back the GDB session. you will notice that GDB (actually the test suite) has set a breakpoint at the mysql_parse() function. You'll see something like this:
[Switching to Thread 0xb317fb90 (LWP 11710)]
Breakpoint 1, mysql_parse (thd=0x8878c18),
inBuf=0x8882290 "select @@version_comment limit 1", length=32,
found_semicolon=0xb317f040) at sql_parse.cc:2870
2870 const char ** found_semicolon)
(gdb)
The above is basically showing you the function call stack and argument addresses being passed to the mysql_parse() function, located in drizzled/sql_parse.cc at line 2870.
To see the full call stack, do:
(gdb) where
You'll see that the call stack goes from the thread scheduler (libevent_thread_proc()) to the parser (do_command(), then dispatch_command(), then mysql_parse()).
To step into the server process, do:
(gdb) step
This will run to the next function call. Simply hit enter to repeat the step. To see what a variable contains at any time, simple do:
(gdb) print name_of_variable
For instance
(gdb) print thd
shows
$1 = (class THD*) 0x8878c18
You can also grab a pointer's member variables, such as the thread's current query ID:
(gdb) print thd->query_id
$2 = 1
You can set another break point (for instance, a function you are interested in) by doing:
(gdb) break function_name
for instance, if I look through the source code, I see that once a SELECT query is issued by the client, the function mysql_select() is called
so I could do:
(gdb) break mysql_select
GDB will inform you a breakpoint has been set, and the line number of the file, like so:
Breakpoint 2 at 0x814ea09: file sql_select.cc, line 2618.
To continue until that breakpoint, do:
(gdb) continue
And you are now at mysql_select()...
If you continue again, and you switch back to your terminal with the drizzle client in it. You should see a drizzle client at the command prompt, like so:
[503][jpipes@serialcoder: /tmp/trunk/client]$ ./drizzle --user=root --port=9306 Welcome to the Drizzle client.. Commands end with ; or \g. Your Drizzle connection id is 1 Server version: 7.0.0-log Source distribution Type 'help;' or '\h' for help. Type '\c' to clear the buffer. drizzle>>
Keep this client open, since you will be executing commands through it.
In the GDB session, type:
(gdb) break mysql_parse (gdb) continue
Then the client, do:
drizzle> SELECT * FROM INFORMATION_SCHEMA.TABLES;
and switch back to the server GDB session. You will see that GDB has broken once more at mysql_parse() and that the inBuf is the "SELECT *FROM INFORMATION_SCHEMA.TABLES"
if a server crash/SEGFAULT occurs, GDB will be interrupted and you will see the fault. At this point, you can get the backtrace (function stack) of where the fault occurred by using the "bt" command:
you can see the code being executed with the "list" command:
(gdb) list
744 - mysql_reset_session_for_next_command()
745 So, initializing the lexical analyser *before* using the query cache
746 is required for the cache to work properly.
747 FIXME: cleanup the dependencies in the code to simplify this.
748 */
749 lex_start(session);
750 session->reset_for_next_command();
751
752 {
753 LEX *lex= session->lex;
you can Step though the code (single instruction at a time) by pressing s or (single line at a time, next line) by pressing n
(gdb) s lex_start (session=0x20128d0) at sql_lex.cc:205(gdb) n 210 lex->unit.init_query(); (gdb) n 211 lex->unit.init_select();
205 LEX *lex= session->lex; (gdb) s 207 lex->session= lex->unit.session= session; (gdb) s 209 lex->context_stack.empty();
For helping development works, please log all debug info in bug tracker.
Courtesy for the content: Jay Pipes
Last Update : --Jobinau 07:00, 22 October 2009 (UTC)