精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
锐英源精品开源心得,转载请注明:“锐英源www.wisestudy.cn,孙老师作品,电话13803810136。需要全文内容也请联系孙老师。
Writing modules for Apache has been somewhat of a mixed affair for me. It's been fun and I've learned a lot, but a lot of times I've spent hours wondering what was wrong with my module. Apache would just segfault and not give a clue to what was wrong. This is where debuggers come to the rescue.遇到segfault,没线索找错误。这时候需要调试来救场。
First of all we need to recompile our Apache httpd binary with the added debugging flags. This is done by defining CFLAGS=-g 调试标志CFLAGS=-g
$ ls apache_1.3.20.tar.gz $ tar -zxf apache_1.3.20.tar.gz $ ls -F apache_1.3.20/ apache_1.3.20.tar.gz $ cd apache_1.3.20/ $ CFLAGS="-g" ./configure --prefix=/home/thomas/build/apache-dev \ --enable-module=so [output of configure] $ make $ make install
Now you need to edit the configuration file httpd.conf to fit your needs or just use this one to test out your modules: 根据需要编辑httpd.conf配置文件,如果不好确定,试用下面的。
ServerType standalone ServerRoot "/home/thomas/build/apache-dev" ServerName localhost PidFile /home/thomas/build/apache-dev/logs/httpd.pid ScoreBoardFile /home/thomas/build/apache-dev/logs/httpd.scoreboard Timeout 300 Port 8080 User thomas Group thomas ServerAdmin thomas@localhost DocumentRoot "/home/thomas/build/apache-dev/htdocs" <Directory /> Options FollowSymLinks AllowOverride None </Directory> <Directory "/home/thomas/build/apache-dev/htdocs"> Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny Allow from all </Directory> <IfModule mod_dir.c> DirectoryIndex index.html </IfModule> AccessFileName .htaccess <Files ~ "^\.ht"> Order allow,deny Deny from all </Files> ErrorLog /home/thomas/build/apache-dev/logs/error_log LogLevel warn LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined CustomLog /home/thomas/build/apache-dev/logs/access_log combined <IfDefine HEADER> LoadModule my_header_module libexec/mod_my_header.so </IfDefine> <IfDefine SERVER> LoadModule my_server_module libexec/mod_my_server.so </IfDefine> <IfDefine ADVANCED_HEADER> LoadModule my_advanced_header_module libexec/mod_my_advanced_header.so MyAdvancedHeader On MyAdvancedHeader_message "this is a test-header" </IfDefine>
If you use the configuration file supplied here you will be able to start your server in single-process mode like this:用上面配置,可以以单进程模式启动服务器:
$ /home/thomas/build/apache-dev/bin/httpd -X -DHEADER # This will load mod_my_header.so $ /home/thomas/build/apache-dev/bin/httpd -X -DSERVER # This will load mod_my_server.so $ /home/thomas/build/apache-dev/bin/httpd -X -DADVANCED_HEADER # This will load mod_my_advanced_header.so
As you can see it is pretty easy and it is just as easy to load it up in your debugger, which the next section is all about.比较容易加载到调试器里。
The most widely used debugger under *NIX environment is gdb, also called The GNU Debugger.
I created a .gdbinit file to make the debugging easier. Please note that there might be a bug in the dump_tables define.创建.gdbinit文件让调试容易些。注意在dump_tables定义里可能有一个bug。
define httpd run -X -f /home/thomas/build/apache-dev/conf/httpd.conf end define dump_table set $t = (table_entry *)((array_header *)$arg0)->elts set $n = ((array_header *)$arg0)->nelts set $i = 0 while $i < $n printf "[%u] '%s'='%s'\n", $i, $t[$i].key, $t[$i].val set $i = $i + 1 end end document dump_table Print the key/value pairs in a table. end define dump_string_array set $a = (char **)((array_header *)$arg0)->elts set $n = (int)((array_header *)$arg0)->nelts set $i = 0 while $i < $n printf "[%u] '%s'\n", $i, $a[$i] set $i = $i + 1 end end document dump_string_array Print all of the elements in an array of strings. end define dump_request set $r = $arg0 printf "[request_rec dump]\n" if $r->the_request != 0x0 printf "r->the_request = '%s'\n", $r->the_request end printf "r->proxyreq = %u\n", $r->proxyreq printf "r->header_only = %u\n", $r->header_only if $r->protocol != 0x0 printf "r->protocol = '%s'\n", $r->protocol end printf "r->proto_num = %u\n", $r->proto_num if $r->hostname != 0x0 printf "r->hostname = '%s'\n", $r->hostname end printf "r->request_time = %u\n", $r->request_time if $r->status_line != 0x0 printf "r->startus_line = '%s'\n", $r->status_line end printf "r->status = %u\n", $r->status if $r->method != 0x0 printf "r->method = '%s'\n", $r->method end printf "r->method_number = %u\n", $r->method_number printf "r->allowed = %u\n", $r->allowed printf "r->sent_bodyct = %u\n", $r->sent_bodyct printf "r->bytes_sent = %u\n", $r->bytes_sent printf "r->mtime = %u\n", $r->mtime printf "r->chunked = %u\n", $r->chunked printf "r->byterange = %u\n", $r->byterange if $r->boundary != 0x0 printf "r->boundary = '%s'\n", $r->boundary end if $r->range != 0x0 printf "r->range = '%s'\n", $r->range end printf "r->clength = %u\n", $r->clength printf "r->remaining = %u\n", $r->remaining printf "r->read_length = %u\n", $r->read_length printf "r->read_body = %u\n", $r->read_body printf "r->read_chunked = %u\n", $r->read_chunked printf "r->expecting_100 = %u\n", $r->expecting_100 if $r->content_type != 0x0 printf "r->content_type = '%s'\n", $r->content_type end if $r->handler != 0x0 printf "r->handler = '%s'\n", $r->handler end if $r->content_encoding != 0x0 printf "r->content_encoding = '%s'\n", $r->content_encoding end if $r->content_language != 0x0 printf "r->content_language = '%s'\n", $r->content_language end if $r->vlist_validator != 0x0 printf "r->vlist_validator = '%s'\n", $r->vlist_validator end printf "r->no_cache = %u\n", $r->no_cache printf "r->no_local_copy = %u\n", $r->no_local_copy if $r->unparsed_uri != 0x0 printf "r->unparsed_uri = '%s'\n", $r->unparsed_uri end if $r->uri != 0x0 printf "r->uri = '%s'\n", $r->uri end if $r->filename != 0x0 printf "r->filename = '%s'\n", $r->filename end if $r->path_info != 0x0 printf "r->path_info = '%s'\n", $r->path_info end if $r->args != 0x0 printf "r->args = '%s'\n", $r->args end end define dump_tables printf "[r->headers_in]\n" dump_table r->headers_in printf "[r->headers_out]\n" dump_table r->headers_out printf "[r->err_headers_out]\n" dump_table r->err_headers_out printf "[r->subprocess_env]\n" dump_table r->subprocess_env printf "[r->notes]\n" dump_table r->notes end
I really didn't feel that comfortable using gdb so I tried on of the graphical frontends to gdb; DDD.
DDD soon became a tool I really liked to use. I like it because it's much easier to see what is going on inside the code. With your cursor you can inspect values of variables and create breakpoints. DDD is downloadable from http://www.gnu.org/software/ddd/ddd.html. Starting DDD with your httpd binary is straightforward:我喜欢用DDD。用鼠标可以观察变量值和创建断点。用如下方式启动DDD,并同时加载httpd。
ddd ./httpd