How can I debug/trace NSAPI applications?
NSAPI applications are run in separate processes on your zeus webserver, one process per virtual server:
In this instance, process 24711 runs NSAPI applications on behalf of virtual server 'test-1'. Process 24709 (zeus.nsapi) is the 'master process' which creates and destroys the individual nsapi runners.bash$ ps -ef ¦ grep zeus root 24704 1 0 14:05:12 ? 0:02 zeus.admin root 24705 24704 0 14:05:12 ? 0:06 zeus.admin root 24708 1 0 14:05:13 ? 0:06 zeus.web root 24709 24708 0 14:05:13 ? 0:01 zeus.nsapi root 24710 24708 0 14:05:13 ? 0:00 zeus.web root 24711 24709 0 14:05:13 ? 0:01 zeus.nsapi test-1 root 24712 24709 0 14:05:13 ? 0:01 zeus.nsapi test-2 You can attach a system call tracer (truss, strace etc) to any of these processes. In particular, if an nsapi runner is prone to failure on startup, attach the tracer to the master process with 'follow fork' (often '-f') enabled (eg, 'strace -f -p 24709').
nsapisnoop
The nsapisnoop program in $ZEUSHOME/web/bin monitors the protocol between the webserver and the nsapi runner. Use as follows:
When the virtual server restarts, it will connect to the running 'nsapisnoop' and log the request-response protocol between the server and the NSAPI runner. From this information, you can derive what NSAPI applications are being run, what arguments they are being passed and what response they are returning.
- Start 'nsapisnoop'
- Stop and start the virtual server you wish to examine (traffic lights!)
In addition, 'nsapisnoop -d2' also dumps all function calls through the __nsapi30_table function table.
How can I attach a debugger to an NSAPI application?
When you next grab a web page that uses this function, the debugger will break in this function. You can step through the function, examining local variables etc.
- Compile your NSAPI module (the .so or .sl library) with -g to include debugging information.
- Start the virtual server that uses the module.
- Determine the pid of the zeus.nsapi process that manages that virtual server:
In this instance, process 24711 runs NSAPI applications on behalf of virtual server 'test-1'. Process 24709 (zeus.nsapi) is the 'master process' which creates and destroys the individual nsapi runners.bash$ ps -ef ¦ grep zeus.nsapi root 24709 24708 0 14:05:13 ? 0:01 zeus.nsapi root 24711 24709 0 14:05:13 ? 0:01 zeus.nsapi test-1 root 24712 24709 0 14:05:13 ? 0:01 zeus.nsapi test-2
- Start your debugger and attach it to the process. Set a breakpoint for the function you want to trace (eg my_func).
bash$ gdb $ZEUSHOME/web/bin/zeus.nsapi (gdb) attach 24711 (gdb) break my_func (gdb) cont
If you want to break in a function that is called at Init, you need to be a bit more clever because the function is called just after the new zeus.nsapi process is forked and execed. Most debugger can't follow forks.
You can use a dummy Init function that blocks for long enough for you to attach a debugger to the new process. pause() and sleep() are good candidates.
/* sleep.c * Use as follows: * Init fn="load-modules" funcs="mysleep" shlib="sleep.so" * Init fn="mysleep" secs="20" */ #include <unistd.h> \/* for sleep() */ #include <stdlib.h> \/* for atoi() */ char *pblock_findval( const char*, const void* ); int mysleep( void *args, void *sn, void *rq ) { const char *secs = pblock_findval( "secs", args ); if( t ) sleep( atoi( secs ) ); return 0; }Compile this up to a .so file, for example:
Using gcc:Using HP cc:gcc -g -c -fPIC sleep.c gcc -shared -o sleep.so sleep.occ -Ae -g -c +z sleep.c ld -b -o sleep.so sleep.oPut the following in your obj.conf, before any other Init directives:
Init fn="load-modules" funcs="mysleep" shlib="sleep.so" Init fn="mysleep" secs="20"(shlib should include the full path to the sleep.so library)
Then when you start your virtual server, you have 20 seconds to figure out the pid and attach a debugger to it!