锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 开源技术 / Apache / Apache调试
服务方向
人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发
联系方式
固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

锐英源精品开源心得,转载请注明:“锐英源www.wisestudy.cn,孙老师作品,电话13803810136。需要全文内容也请联系孙老师。

Apache调试

Debugging

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,没线索找错误。这时候需要调试来救场。

Building an Apache for debugging调试模式编译Apache

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.比较容易加载到调试器里。

Be aware of problems debugging code with loadable modules认识加载模块里调试代码的问题

gdb

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

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
友情链接
版权所有 Copyright(c)2004-2021 锐英源软件
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州大学北校区院(文化路97号院)内