Académique Documents
Professionnel Documents
Culture Documents
Presentation overview
An introduction to the Apache source code layout An introduction to key concepts such as modules, buckets, brigades, hooks, filters, and MPMs An introduction to several tools that can be used to perform post-mortem analysis An introduction to several tools that can be used to debug transient server problems
Apache layout
What is Apache?
Flexible and extensible opensource web server Supports HTTP versions 0.9, 1.0 and 1.1 Ships with a variety of modules that can be used to secure communications and transform content Supports virtual hosting Supports static and dynamic content delivery The list goes on and on
Apache terminology
Resource pools
Pools are used to simplify memory management Pools are created and destroyed automatically by the server core Pools have a lifetime associated with them (e.g, a request pool is created when a request arrives, and destroyed after the request is processed) apr_pools.h provides a thorough description of the pool API and the underlying allocator
mpm_common.h, prefork.c and worker.c contain the MPM, prefork and worker MPM implementations
Filters
Filters are used to read and transform data as its read from and written to the network Filter chains are used to allow the output from one filter to become the input to another filter Two type of filters
Input filters (e.g., mod_deflate, mod_ssl ) Output filters (e.g., mod_ssl, mod_headers)
Debugging
Why debug?
Because software breaks Because administrators get frustrated with messages similar to the following:
[Sat Feb 04 13:00:27 2006] [notice] child pid 8581 exit signal Segmentation fault (11), possible coredump in /var/tmp/apache2
Types of debugging
Post-mortem debugging Transient problem debugging Reverse engineering
Postmortem debugging
Maintainer mode
Builds Apache with debugging support and custom instrumentation Enabled at configure time
$ ./configure --enable-maintainer-mode \ --enable-exception-hook \ --enable-mods-shared=most \ --enable-deflate=shared \ --prefix=/opt/apache2
mod_backtrace
Writes a stack trace to a logfile each time a critical signal (e.g., SIGSEGV) is received Utilizes the Apache exception hook Can help with diagnosing problems on platforms that dont reliably create core files Supports Linux and FreeBSD Solaris patch available on my website
Enable module
LoadModule backtrace_module modules/mod_backtrace.so EnableExceptionHook On
GDB macros
Apache comes with numerous GDB macros to print brigades, buckets, strings, filters, memnodes, tables, and process and server records Macros are located in $SRCROOT/.gdbinit Can be sourced using the gdb source command
Curl
Versatile command line utility that can be used to debug web-based problems Curl contains several advanced options to print protocol headers and connection errors Invaluable utility for locating misbehaving servers and applications
Curl example
$ curl -v --user-agent "CURL DEBUG (`date`)" -H "X-foo: yikes" http://daemons.net
About to connect() to daemons.net port 80 Trying 66.148.84.65... * connected Connected to daemons.net (66.148.84.65) port 80 > GET / HTTP/1.1 User-Agent: CURL DEBUG (Sat Feb 4 23:02:36 EST 2006) Host: daemons.net Pragma: no-cache Accept: */* X-foo: yikes < HTTP/1.1 200 OK < Date: Sun, 05 Feb 2006 04:04:13 GMT < Server: Apache < Last-Modified: Sun, 20 Jun 2004 14:39:21 GMT < ETag: "5c186-912-c108d840" < Accept-Ranges: bytes < Content-Length: 2322 < Content-Type: text/html
DTrace
Dynamic tracing facility introduced in Solaris 10 Can dynamically instrument applications and the Solaris kernel down to the instruction level Utilizes 30k+ probes distributed throughout the Solaris kernel Designed to be used on production systems No overhead when probes arent enabled
Dtrace example #1
Viewing system calls by Apache process
$ dtrace -n 'syscall:::entry /execname == "httpd"/ { @calls[probefunc] = count(); }'
Dtrace example #2
Determining WHO called writev
$ dtrace -n 'syscall::writev:entry / execname == "httpd" / { ustack(); }'
Dtrace example #3
Tracing execution flow per request
#pragma D option flowindent pid$target::ap_process_request:entry { self->trace = 1; } pid$target::ap_process_request:return { self->trace = 0; } pid$target:::entry, pid$target:::return / self->trace / {}
Dtrace example #4
Tracing execution flow into the kernel
#pragma D option flowindent pid$target::ap_read_request:entry { self->trace = 1; } pid$target::ap_read_request:return { self->trace = 0; } pid$target:::entry, pid$target:::return, fbt:::entry, fbt:::return / self->trace / {}
Dtrace example #5
Watching Logical Apache I/O operations
syscall::write:entry / execname == "httpd" / { printf("Apache wrote (%s) to fd %d (%s\n", probefunc, arg0, fds[arg0].fi_pathname); } syscall::read:entry / execname == "httpd" / { printf("Apache read (%s) from fd %d (%s)\n", probefunc, arg0, fds[arg0].fi_pathname); }
Dtrace example #6
Measuring write size
$ dtrace -n 'syscall::read:return / execname == "httpd" && errno == 0 / { @distribution["Average read size"] = quantize(arg1); }'
Dtrace example #7
Measuring request processing time
pid$target::ap_read_request:entry { self->ts = timestamp; } pid$target::ap_read_request:return { self->method = arg1 == 0 ? "Unknown" : copyinstr(*(uintptr_t *)copyin(arg1 + 68,4)); self->uuri = arg1 == 0 ? "Unknown" : copyinstr(*(uintptr_t *)copyin(arg1 + 200,4)); } pid$target::ap_process_request:return { printf("Processed %s %s in %d microseconds\n", self->method, self->uuri, (timestamp - self->ts) / 1000000); self->uuri = 0; self->ts = 0; }
Conclusion
Debugging is cool! Debugging is great! Now its time for me to escape! :-)
Questions?
References
Apache: http://apache.org Chaosreader: http://users.tpg.com.au/bdgcvb/chaosreader.html Curl: http://curl.haxx.se/ Dtrace: http://opensolaris.org/os/community/dtrace/ Debugging Web Applications: http://www.samag.com/articles/2006/0603/ Ethereal: http://www.ethereal.com/ mod_backtrace: http://people.apache.org/~trawick/exception_hook.htm Observing I/O Behavior with the DTraceToolkit: http://www.samag.com/documents/s=9915/sam0512a/051 2a.htm