Show wrapper.asc syntax highlighted
Using valgrind, strace, and ltrace with EmStar
==============================================
The EmStar Team
$Id: wrapper.asc,v 1.1 2005/09/01 02:15:39 girod Exp $
Valgrind, strace, and ltrace are useful for debugging EmStar programs.
These programs can work as "wrappers" that your program runs "inside"
and analyses it as it runs.
Using Debug Wrappers
--------------------
To invoke your EmStar module inside a "wrapper", you can add it to
your emrun process block, inside the `cmd=` line (for example, to
run `valgrind`):
-------
cmd = "/usr/bin/valgrind --tool=memcheck -v -v mote/hostmoted -p $port -m $type -r $index";
-------
Note that many EmRun macros include an `$debug` argument for exactly
this purpose, so this can be done more conveniently (without changing
the macro definition itself) this way:
-------
&mote_hostmote(serialPort=/dev/ttyS0,debug="/usr/bin/valgrind --tool=memcheck -v -v");
-------
Valgrind
--------
http://valgrind.org/[Valgrind] is an x86 emulator that works as a
memory debugger and profiler and can detect memory leaks as well as
many other types of memory error.
Because Valgrind is an emulator, it's not possible to "attach" to
a running process the way other tools such as strace and gdb can.
Rather, it must run your program within its emulation framework.
Generally speaking, Valgrind works well with EmStar programs.
The main problem that crops up has to do with `ioctl()`
calls that Valgrind can't check for validity. These show up as
spurious errors or "Unhandled ioctl()" warnings. Valgrind also
seems to generate spurious errors in `pthread` library calls.
The typical arguments to valgrind are "--tool=memcheck -v -v"
strace
------
`strace` traces the use of system calls. Since EmStar IPC operations
are always based on system calls, strace is a powerful tool for
finding out what your program is doing. A sample trace of the sample
program skeletons/hello_world is shown here:
------
girod@wren:/scratch/girod/emstar/obj.i686-linux$ strace skeletons/hello_world
execve("skeletons/hello_world", ["skeletons/hello_world"], [/* 20 vars */]) = 0
uname({sys="Linux", node="wren", ...}) = 0
[...]
open("/dev/fusd/control", O_RDWR|O_NONBLOCK) = 3
write(3, "\317\223kz\0\0\0\0\0\0\0\0\0\0\0\0misc/hello_world"..., 76) = 76
open("/dev/fusd/status", O_RDWR|O_NONBLOCK) = 5
ioctl(5, 0x4666, 0xbffff9b8) = 0
write(5, "misc/hello_world", 16) = 16
poll([{fd=5, events=POLLIN, revents=POLLIN}], 1, -1) = 1
close(5) = 0
poll([{fd=3, events=POLLIN|POLLPRI|POLLERR}], 1, 0) = 0
ioctl(3, 0, 0) = -1 ENOTTY (Inappropriate ioctl for device)
poll([{fd=3, events=POLLIN|POLLPRI|POLLERR}], 1, 0) = 0
ioctl(3, 0, 0) = -1 ENOTTY (Inappropriate ioctl for device)
fstat64(3, {st_mode=S_IFCHR|0777, st_rdev=makedev(242, 0), ...}) = 0
fcntl64(3, F_GETFL) = 0x802 (flags O_RDWR|O_NONBLOCK)
write(2, "Now \'cat /dev/misc/hello_world\' "..., 50Now 'cat /dev/misc/hello_world' to get the status
) = 50
write(2, "Send SIGTERM to shutdown the sta"..., 44Send SIGTERM to shutdown the status device.
) = 44
open("/dev/emrun/.int/control", O_RDWR) = -1 ENOENT (No such file or directory)
pipe([5, 6]) = 0
fcntl64(6, F_GETFL) = 0x1 (flags O_WRONLY)
fcntl64(6, F_SETFL, O_WRONLY|O_NONBLOCK) = 0
fcntl64(5, F_GETFL) = 0 (flags O_RDONLY)
fcntl64(5, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
poll([{fd=5, events=POLLIN|POLLPRI|POLLERR}], 1, 0) = 0
ioctl(5, 0, 0) = -1 EINVAL (Invalid argument)
poll([{fd=5, events=POLLIN|POLLPRI|POLLERR}], 1, 0) = 0
ioctl(5, 0, 0) = -1 EINVAL (Invalid argument)
fstat64(5, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
fcntl64(5, F_GETFL) = 0x800 (flags O_RDONLY|O_NONBLOCK)
rt_sigaction(SIGTERM, {0x400b17a0, [TERM], SA_RESTORER|SA_RESTART, 0x401a16f8}, {SIG_DFL}, 8) = 0
rt_sigaction(SIGINT, {0x400b17a0, [INT], SA_RESTORER|SA_RESTART, 0x401a16f8}, {SIG_DFL}, 8) = 0
rt_sigaction(SIGHUP, {0x400b17a0, [HUP], SA_RESTORER|SA_RESTART, 0x401a16f8}, {SIG_DFL}, 8) = 0
getpid() = 6666
poll(
------
This trace ends in an unfinished `poll()` call.. it's blocked here
waiting for input.
System calls typically reference file descriptors by number, and these
will show up in the system call trace. To find out what files those
numbers map to, you can use `ls` to list the proc/PID/fd directory:
-----
girod@wren:~$ ls -l /proc/6666/fd
total 0
lrwx------ 1 girod girod 64 Aug 31 19:10 0 -> /dev/pts/0
lrwx------ 1 girod girod 64 Aug 31 19:10 1 -> /dev/pts/0
lrwx------ 1 girod girod 64 Aug 31 19:10 2 -> /dev/pts/0
lrwx------ 1 girod girod 64 Aug 31 19:10 3 -> /dev/fusd/control
lr-x------ 1 girod girod 64 Aug 31 19:10 4 -> /dev/null
lr-x------ 1 girod girod 64 Aug 31 19:10 5 -> pipe:[1272834]
l-wx------ 1 girod girod 64 Aug 31 19:10 6 -> pipe:[1272834]
-----
You can also attach to a process using strace by specifying the
process ID with the `-p` argument. Note that at most one instance of
strace (or GDB) can attach to a single process.
ltrace
------
ltrace is very similar to strace, only traces standard library calls.
See more files for this project here